apa yang Anda maksud dengan " string konstan literal" dalam C (bukan C ++)
gbulmer
1
... char * nama dapat dibuat untuk menunjuk ke string string yang konstan
Iceman
konstanta dalam "string konstan literal" adalah mubazir, karena semua string literal dalam entitas teori konstan. Ini isi dari variabel yang dapat dibuat konstan atau bisa berubah. Deklarasi "const" hanya akan menimbulkan kesalahan waktu kompilasi jika Anda mencoba untuk mengubah konten karakter yang ditunjuk oleh "name"
Cupcake
Sederhana: nama "char * name" adalah pointer ke char, yaitu keduanya dapat diubah di sini. "const char * name" name adalah pointer ke const char yaitu pointer dapat berubah tetapi tidak char.
akD
Baca hal-hal ini dari kanan ke kiri.
Jiapeng Zhang
Jawaban:
406
char*adalah pointer yang bisa berubah ke karakter / string yang bisa berubah .
const char*adalah pointer yang bisa berubah ke karakter / string yang tidak dapat diubah . Anda tidak dapat mengubah konten lokasi yang ditunjuk oleh pointer ini. Juga, kompiler diminta untuk memberikan pesan kesalahan saat Anda mencoba melakukannya. Untuk alasan yang sama, konversi dari const char *ke char*tidak digunakan lagi.
char* constadalah pointer yang tidak dapat diubah (tidak dapat menunjuk ke lokasi lain) tetapi konten lokasi yang ditunjukkannya dapat berubah .
const char* constadalah pointer yang tidak dapat diubah ke karakter / string yang tidak dapat diubah .
Kebingungan dapat diselesaikan dengan penggunaan variabel setelah pernyataan yang disebutkan di atas dan dengan memberikan referensi ke variabel itu.
ankit.karwasra
3
@ ankit.karwasra, Anda melewatkan satu lagi:char const *
Pacerier
Saya kira dua opsi dengan karakter / string yang dapat berubah sangat berbahaya, karena Anda dapat melakukan memori kesalahan segmetasi, dan jika Anda benar-benar pintar, Anda dapat meretas komputer. Itulah mengapa kompiler selalu menunjukkan peringatan dalam implementasi yang saya pikir
Daniel N.
1
Tidak akan bermutasi char *memberikan kesalahan segmentasi saat menjalankan?
Divyanshu Maithani
1
Jadi saya menggunakan constjika saya ingin kompiler memberikan kesalahan jika saya lupa dan mengubah data secara tidak sengaja, bukan?
Akuntan م
43
char*name
Anda dapat mengubah arang ke nametitik mana , dan juga arang di mana ia menunjuk.
constchar* name
Anda dapat mengubah arang ke nametitik mana , tetapi Anda tidak dapat mengubah arang di mana ia menunjuk. koreksi: Anda dapat mengubah pointer, tetapi bukan karakter yang namemengarah ke ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , lihat "Contoh" ). Dalam kasus ini, constspecifier berlaku untuk char, bukan tanda bintang.
Menurut halaman MSDN dan http://en.cppreference.com/w/cpp/language/declarations , constsebelum itu *adalah bagian dari urutan decek-specifier, sedangkan constafter *adalah bagian dari deklarator.
Urutan specifier deklarasi dapat diikuti oleh beberapa deklarator, itulah sebabnya const char * c1, c2menyatakan c1sebagaiconst char * dan c2sebagai const char.
EDIT:
Dari komentar, pertanyaan Anda tampaknya bertanya tentang perbedaan antara dua deklarasi ketika pointer menunjuk ke string literal.
Dalam hal ini, Anda tidak boleh memodifikasi char ke nametitik mana , karena dapat menghasilkan Perilaku Tidak Terdefinisi . Literal string dapat dialokasikan di wilayah memori hanya baca (implementasi ditentukan) dan program pengguna tidak boleh memodifikasinya. Setiap upaya untuk melakukannya menghasilkan Perilaku Tidak Terdefinisi.
Jadi satu-satunya perbedaan dalam kasus itu (penggunaan dengan string literal) adalah bahwa deklarasi kedua memberi Anda sedikit keuntungan. Compiler biasanya akan memberi Anda peringatan jika Anda mencoba untuk memodifikasi string literal dalam kasus kedua.
#include<string.h>int main(){char*str1 ="string Literal";constchar*str2 ="string Literal";char source[]="Sample string";
strcpy(str1,source);//No warning or error, just Undefined Behavior
strcpy(str2,source);//Compiler issues a warningreturn0;}
Keluaran:
cc1: peringatan diperlakukan sebagai kesalahan
prog.c: Dalam fungsi 'utama':
prog.c: 9: kesalahan: meneruskan argumen 1 dari 'strcpy' membuang kualifikasi dari tipe target penunjuk
Perhatikan kompiler memperingatkan untuk kasus kedua tetapi tidak untuk yang pertama.
Terima kasih .. saya bercampur dengan string string literal, yang didefinisikan sebagai: char * name = "String Literal"; Mengubah "String Literal" tidak ditentukan ..
Iceman
@ user1279782: Err, Tunggu! Apakah Anda berbicara tentang poin yang menunjuk ke string literal di sini? Dalam hal ini Anda tidak boleh memodifikasi char yang menjadi namepoin dalam kedua kasus tersebut. Ini bisa menghasilkan UB.
Alok Simpan
Ya, itu intinya. Jadi dalam hal ini char * nama dan const char * nama berperilaku serupa, kan?
Iceman
4
Jawaban ini sangat ambigu atau hanya salah. Saya akan menafsirkan "Anda tidak dapat mengubah arang ke mana nama poin, tetapi Anda dapat mengubah arang di mana ia menunjuk." Karena tidak dapat memodifikasi pointer itu sendiri, tetapi dapat memodifikasi lokasi memori yang ditunjuknya, yang salah: ideone.com/6lUY9s sebagai alternatif untuk C murni: ideone.com/x3PcTP
shroudednight
1
@shroudednight: Anda perlu belajar sedikit tentang perilaku yang tidak terdefinisi, dan perlu membedakan antara: diizinkan dan tidak boleh dilakukan. :)
Alok Save
16
char mystring[101]="My sample string";constchar* constcharp = mystring;// (1)charconst* charconstp = mystring;// (2) the same as (1)char*const charpconst = mystring;// (3)
constcharp++;// ok
charconstp++;// ok
charpconst++;// compile error
constcharp[3]='\0';// compile error
charconstp[3]='\0';// compile error
charpconst[3]='\0';// ok// String literalschar* lcharp ="My string literal";constchar* lconstcharp ="My string literal";
lcharp[0]='X';// Segmentation fault (crash) during run-time
lconstcharp[0]='X';// compile error// *not* a string literalconstchar astr[101]="My mutable string";
astr[0]='X';// compile error((char*)astr)[0]='X';// ok
Tidak satu pun dari petunjuk Anda yang menunjuk ke "literal string konstan" sesuai pertanyaan.
kaf
Perlu dicatat bahwa mengubah char *nilai memberikan kesalahan segmentasi karena kami mencoba untuk memodifikasi string literal (yang ada dalam memori hanya baca)
Divyanshu Maithani
10
Dalam kedua kasus Anda tidak dapat memodifikasi string literal, terlepas dari apakah pointer ke string literal tersebut dinyatakan sebagai char *atauconst char * .
Namun, perbedaannya adalah bahwa jika pointer const char *maka compiler harus memberikan diagnostik jika Anda mencoba untuk memodifikasi nilai menunjuk-ke, tetapi jika pointer itu char *maka tidak.
"Dalam kedua kasus Anda tidak dapat memodifikasi string literal, terlepas dari apakah ... [itu] dinyatakan sebagai char * atau const char *" Saya setuju bahwa programmer tidak boleh mencoba, tetapi apakah Anda mengatakan bahwa setiap kompiler C, pada setiap platform akan menolak kode tersebut, mengatur agar kode gagal pada waktu berjalan, atau yang lainnya? Saya percaya, satu file dapat memiliki definisi dan inisialisasi, dan file lain mungkin berisi extern ... namedan memiliki *name = 'X';. Pada 'sistem operasi yang tepat', itu mungkin gagal, tetapi pada sistem embedded, saya berharap untuk melakukan sesuatu platform / kompiler spesifik.
gbulmer
@ gbulmer: Anda tidak dapat mengubah string literal dalam program C yang benar. Apa program C yang salah yang mencoba dapat mengakibatkan tidak ada di sini atau di sana.
kafe
@ gbulmer: Salah satu definisi yang berguna adalah program yang tidak melanggar batasan apa pun yang ditentukan oleh standar bahasa C. Dengan kata lain, sebuah program yang memodifikasi string literal tidak benar dengan cara yang sama seperti program yang mereferensi pointer nol atau melakukan pembagian dengan 0 tidak benar.
caf
caf - saya pikir itu mungkin yang Anda maksud. Kemudian "Dalam kedua kasus Anda tidak dapat memodifikasi string literal" tampaknya lebih menyatakannya. Akan akurat untuk mengatakan "Dalam kedua kasus kendala yang ditentukan oleh standar bahasa C telah rusak, terlepas .... Tidak mungkin bagi kompiler atau sistem waktu berjalan untuk mengidentifikasi pelanggaran standar dalam semua kasus." Saya menganggap standar mengambil posisi bahwa efeknya tidak terdefinisi?
gbulmer
1
Ketika sebuah standar tidak dapat menyatakan apa pun, saya pikir mendefinisikan perilaku sebagai 'tidak terdefinisi' tampaknya menjadi batas yang tepat dan bermanfaat. Untuk menegaskan hubungan, 'program C yang benar' ' tidak dapat melakukan dereferensi penunjuk nol' sama dengan membuktikan masalah penghentian. Tapi saya tidak keberatan. Saya tidak akan melakukannya dan berharap untuk lolos dengan 'scott free' :-)
gbulmer
4
KASUS 1:
char*str ="Hello";
str[0]='M'//Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Set di atas str untuk menunjuk ke nilai literal "Hello" yang dikodekan dalam gambar biner program, yang ditandai sebagai hanya-baca dalam memori, berarti setiap perubahan dalam string literal ini ilegal dan yang akan menyebabkan kesalahan segmentasi.
KASUS 2:
constchar*str ="Hello";
str[0]='M'//Compile time error
KASUS 3:
char str[]="Hello";
str[0]='M';// legal and change the str = "Mello".
Yang pertama Anda benar-benar dapat berubah jika Anda mau, yang kedua Anda tidak bisa. Baca tentang constkebenaran (ada beberapa panduan bagus tentang perbedaannya). Ada juga di char const * namemana Anda tidak bisa mengulanginya.
Tidak ada banyak perbedaan antara 2 dan keduanya dapat dilihat sebagai benar. Karena warisan yang lama dari kode C, string literal memiliki tipe char[], tidak const char[], dan ada banyak kode lama yang juga menerimachar * alih-alihconst char * , bahkan ketika mereka tidak mengubah argumen.
Perbedaan utama dari 2 secara umum adalah bahwa *cnameatau cname[n]akan mengevaluasi ke nilai tipe const char, sedangkan *nameatau name[n]akan mengevaluasi ke tipe nilai char, yang merupakan nilai yang dapat dimodifikasi . Compiler yang sesuai diperlukan untuk menghasilkan pesan diagnostik jika target penugasan bukan nilai yang dapat dimodifikasi ; itu tidak perlu menghasilkan peringatan tentang penugasan ke nilai jenis char:
name[0]='x';// no diagnostics *needed*
cname[0]='x';// a conforming compiler *must* produce a diagnostics message
Kompiler tidak diharuskan untuk menghentikan kompilasi dalam kedua kasus; cukup itu menghasilkan peringatan untuk tugas cname[0]. Program yang dihasilkan bukan program yang benar . Perilaku konstruk tidak terdefinisi . Mungkin macet, atau bahkan lebih buruk, mungkin tidak macet, dan mungkin mengubah string literal dalam memori.
Jawaban:
char*
adalah pointer yang bisa berubah ke karakter / string yang bisa berubah .const char*
adalah pointer yang bisa berubah ke karakter / string yang tidak dapat diubah . Anda tidak dapat mengubah konten lokasi yang ditunjuk oleh pointer ini. Juga, kompiler diminta untuk memberikan pesan kesalahan saat Anda mencoba melakukannya. Untuk alasan yang sama, konversi dariconst char *
kechar*
tidak digunakan lagi.char* const
adalah pointer yang tidak dapat diubah (tidak dapat menunjuk ke lokasi lain) tetapi konten lokasi yang ditunjukkannya dapat berubah .const char* const
adalah pointer yang tidak dapat diubah ke karakter / string yang tidak dapat diubah .sumber
char const *
char *
memberikan kesalahan segmentasi saat menjalankan?const
jika saya ingin kompiler memberikan kesalahan jika saya lupa dan mengubah data secara tidak sengaja, bukan?Anda dapat mengubah arang ke
name
titik mana , dan juga arang di mana ia menunjuk.Anda dapat mengubah arang kename
titik mana , tetapi Anda tidak dapat mengubah arang di mana ia menunjuk.koreksi: Anda dapat mengubah pointer, tetapi bukan karakter yang
name
mengarah ke ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , lihat "Contoh" ). Dalam kasus ini,const
specifier berlaku untukchar
, bukan tanda bintang.Menurut halaman MSDN dan http://en.cppreference.com/w/cpp/language/declarations ,
const
sebelum itu*
adalah bagian dari urutan decek-specifier, sedangkanconst
after*
adalah bagian dari deklarator.Urutan specifier deklarasi dapat diikuti oleh beberapa deklarator, itulah sebabnya
const char * c1, c2
menyatakanc1
sebagaiconst char *
danc2
sebagaiconst char
.EDIT:
Dari komentar, pertanyaan Anda tampaknya bertanya tentang perbedaan antara dua deklarasi ketika pointer menunjuk ke string literal.
Dalam hal ini, Anda tidak boleh memodifikasi char ke
name
titik mana , karena dapat menghasilkan Perilaku Tidak Terdefinisi . Literal string dapat dialokasikan di wilayah memori hanya baca (implementasi ditentukan) dan program pengguna tidak boleh memodifikasinya. Setiap upaya untuk melakukannya menghasilkan Perilaku Tidak Terdefinisi.Jadi satu-satunya perbedaan dalam kasus itu (penggunaan dengan string literal) adalah bahwa deklarasi kedua memberi Anda sedikit keuntungan. Compiler biasanya akan memberi Anda peringatan jika Anda mencoba untuk memodifikasi string literal dalam kasus kedua.
Contoh Contoh Online:
Keluaran:
Perhatikan kompiler memperingatkan untuk kasus kedua tetapi tidak untuk yang pertama.
sumber
name
poin dalam kedua kasus tersebut. Ini bisa menghasilkan UB.sumber
char *
nilai memberikan kesalahan segmentasi karena kami mencoba untuk memodifikasi string literal (yang ada dalam memori hanya baca)Dalam kedua kasus Anda tidak dapat memodifikasi string literal, terlepas dari apakah pointer ke string literal tersebut dinyatakan sebagai
char *
atauconst char *
.Namun, perbedaannya adalah bahwa jika pointer
const char *
maka compiler harus memberikan diagnostik jika Anda mencoba untuk memodifikasi nilai menunjuk-ke, tetapi jika pointer ituchar *
maka tidak.sumber
extern ... name
dan memiliki*name = 'X';
. Pada 'sistem operasi yang tepat', itu mungkin gagal, tetapi pada sistem embedded, saya berharap untuk melakukan sesuatu platform / kompiler spesifik.KASUS 1:
Set di atas str untuk menunjuk ke nilai literal "Hello" yang dikodekan dalam gambar biner program, yang ditandai sebagai hanya-baca dalam memori, berarti setiap perubahan dalam string literal ini ilegal dan yang akan menyebabkan kesalahan segmentasi.
KASUS 2:
KASUS 3:
sumber
Yang pertama Anda benar-benar dapat berubah jika Anda mau, yang kedua Anda tidak bisa. Baca tentang
const
kebenaran (ada beberapa panduan bagus tentang perbedaannya). Ada juga dichar const * name
mana Anda tidak bisa mengulanginya.sumber
Pertanyaannya adalah apa bedanya
yang menunjuk ke string konstan literal, dan
Yaitu diberikan
dan
Tidak ada banyak perbedaan antara 2 dan keduanya dapat dilihat sebagai benar. Karena warisan yang lama dari kode C, string literal memiliki tipe
char[]
, tidakconst char[]
, dan ada banyak kode lama yang juga menerimachar *
alih-alihconst char *
, bahkan ketika mereka tidak mengubah argumen.Perbedaan utama dari 2 secara umum adalah bahwa
*cname
ataucname[n]
akan mengevaluasi ke nilai tipeconst char
, sedangkan*name
atauname[n]
akan mengevaluasi ke tipe nilaichar
, yang merupakan nilai yang dapat dimodifikasi . Compiler yang sesuai diperlukan untuk menghasilkan pesan diagnostik jika target penugasan bukan nilai yang dapat dimodifikasi ; itu tidak perlu menghasilkan peringatan tentang penugasan ke nilai jenischar
:Kompiler tidak diharuskan untuk menghentikan kompilasi dalam kedua kasus; cukup itu menghasilkan peringatan untuk tugas
cname[0]
. Program yang dihasilkan bukan program yang benar . Perilaku konstruk tidak terdefinisi . Mungkin macet, atau bahkan lebih buruk, mungkin tidak macet, dan mungkin mengubah string literal dalam memori.sumber
Sebenarnya,
char* name
bukan pointer ke konstanta, tetapi pointer ke variabel. Anda mungkin berbicara tentang pertanyaan lain ini.Apa perbedaan antara char * const dan const char *?
sumber