Char * ve const char * arasındaki fark nedir?


177

Arasındaki fark nedir

char* name

sabit dize değişmezine işaret eder ve

const char* name

" sabit dize hazır bilgisi" ile ne demek istiyorsun (C ++ değil)
gbulmer

1
... char * adı sabit bir dizgi değişmezine işaret etmek için kullanılabilir
Iceman

"sabit dize değişmezi" içindeki sabit gereksizdir, çünkü tüm dize değişmezleri teoride sabit varlıklardır. Değişkenin içeriği sabit veya değişken hale getirilebilir. Eğer "name" ile gösterilen karakterin içeriğini değiştirmeye çalışırsanız "const" deklarasyonu derleme zamanı hatası verecektir
Cupcake

Basit: "char * name" adı char için bir göstericidir, yani her ikisi de burada değiştirilebilir. "const char * adı" adı const char için bir işaretçi yani işaretçi değişebilir ancak char değil.
akD

Bunları sağdan sola doğru okuyun.
Jiapeng Zhang

Yanıtlar:


406

char*Bir olan değişken bir işaretçi değişken karakter / dizesi.

const char*Bir olan değişken bir işaretçi değişmez karakter / dizesi. Bu işaretçinin işaret ettiği konumların içeriğini değiştiremezsiniz. Ayrıca, derleyicilerin bunu yapmaya çalıştığınızda hata iletileri vermeleri gerekir. Aynı nedenle, gelen dönüşüm const char *To char*kullanımdan kaldırıldı.

char* constBir olduğu değişmez işaretçi (diğer herhangi bir konuma işaret olamaz) , ancak bu noktalar olan konumun içeriği değişebilir .

const char* constBir olan değişmez bir işaretçi değişmez karakter / dizesi.


4
Yukarıda belirtilen ifadelerden sonra ve bu değişkene atıfta bulunarak bir değişkenin kullanımı ile karışıklık giderilebilir.
ankit.karwasra

3
@ ankit.karwasra, Bir daha kaçırdın:char const *
Pacerier

Değişken karakter / dize ile iki seçenek son derece tehlikelidir, çünkü bir bölümleme hatası belleği yapabilir ve gerçekten akıllıysanız bilgisayarı hackleyebilirsiniz. Bu yüzden derleyiciler her zaman bence bu uygulamalarda uyarılar gösterdi
Daniel N.

1
Mutasyona geçme char *çalışırken segmentasyon hatası vermeyecek mi?
Divyanshu Maithani

1
Kullandığım Yani constben unuttum ve sağ, yanlışlıkla verileri değişti eğer derleyici hata vermek isterseniz?
Muhasebeci م

43
char *name

Hangi namenoktayı ve hangi noktayı gösterdiğini değiştirebilirsiniz .

const char* name

Karakteri hangi namenoktalara çevirebilirsiniz, fakat işaret ettiği karakteri değiştiremezsiniz.
düzeltme: Sen işaretçi değiştirebilirsiniz, ancak değil karakter hangi nameişaret ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , bkz "Örnekler" ). Bu durumda, constbelirteç charyıldız işareti için geçerli değildir.

MSDN sayfa ve göre http://en.cppreference.com/w/cpp/language/declarations , constönce *ederken, decl-belirteci dizisinin bir parçası olan constsonra *Bildiricisi bir parçasıdır.
Bir bildirim belirteci dizisi nedenle birden fazla declarators, takip edilebilir const char * c1, c2beyan c1olarak const char *ve c2şekilde const char.

DÜZENLE:

Yorumlardan, sorunuz işaretçi bir dize değişmezine işaret ettiğinde iki bildirim arasındaki farkı soruyor gibi görünüyor.

Bu durumda, olmamalı hangi kömürü değiştirmek nameo yol açabilir gibi noktalarda Tanımsız Davranış . Dize değişmezleri salt okunur bellek bölgelerine tahsis edilebilir (uygulama tanımlı) ve bir kullanıcı programı bunu hiçbir şekilde değiştirmemelidir. Bunu yapmaya yönelik herhangi bir girişim Tanımsız Davranış ile sonuçlanır.

Bu durumda (dize değişmez değerleri ile kullanım) tek fark, ikinci bildirimin size küçük bir avantaj sağlamasıdır. Derleyiciler, ikinci durumda dize hazır bilgisini değiştirmeye çalışırsanız genellikle size bir uyarı verir.

Online Örnek Örnek:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

Çıktı:

cc1: uyarılar hata olarak değerlendiriliyor
prog.c: 'main' işlevinde:
prog.c: 9: hata: 'strcpy' öğesinin 1 argümanını iletme niteleyicileri işaretçi hedef türünden atar

Derleyici ikinci durum için uyarır, ancak ilk durum için uyarmaz.


Teşekkürler .. i olarak tanımlanan sabit dize değişmeziyle karıştırıyordu: char * name = "String Literal"; "String Literal" kelimesinin değiştirilmesi tanımsız ..
Iceman

@ user1279782: Hata, Bekle! Burada dizgi değişmezlerini gösteren noktalardan mı bahsediyorsunuz? Bu durumda sen olmamalıdır hangi kömürü değiştirmek nameya case.It noktaları UB neden olabilir.
Alok

Evet, mesele buydu. Bu durumda char * name ve const char * name benzer davranır, değil mi?
Iceman

4
Bu cevap ya son derece belirsiz ya da sadece yanlıştır. "Adı işaret eden karakteri değiştiremezsiniz, ancak işaret ettiği karakteri değiştirebilirsiniz." : İşaretçi kendisinde değişiklik mümkün, ama hatalı olan işaret eden bellek konumunu değiştirmek mümkün olmayan zamanda ideone.com/6lUY9s : Saf C alternatif ideone.com/x3PcTP
shroudednight

1
@ shroudednight: Tanımsız davranışlar hakkında biraz daha fazla bilgi edinmeniz ve aşağıdakileri ayırmanız gerekir: izin verilen ve yapılmaması gereken. :)
Alok Kaydet

16
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * 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 literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok

1
İşaretçilerinizin hiçbiri soruya göre "sabit dize değişmezlerini" göstermiyor.
caf

char *Bir dizgi değişmezini (salt okunur bellekte bulunur) değiştirmeye çalıştığımızdan , değeri değiştirmenin segmentasyon hatası verdiğini belirtmek gerekir
Divyanshu Maithani

10

Her iki durumda da, bir dize değişmezinin işaretçisinin char *veyaconst char * .

Ancak fark, işaretçi ise, işaretçi const char *değerini değiştirmeye çalışırsanız derleyici bir tanı vermelidir, ancak işaretçi ise değiştirmez char *.


1
"Her iki durumda da ... [it] 'in char * veya const char * olarak beyan edilip edilmediğine bakılmaksızın bir dizgi değişmezini değiştiremezsiniz. Programcının denememesi gerektiğini kabul ediyorum, ancak her C derleyicisinin her Platform kodu reddedecek, kodun çalışma zamanında başarısız olmasını ayarlayacak mı, yoksa başka bir şey mi? Bir dosyanın tanımı ve başlatılması olabilir ve başka bir dosya içerebilir extern ... nameve sahip olabilir *name = 'X';. 'Uygun işletim sisteminde', bu başarısız olabilir, ancak gömülü sistemlerde, platform / derleyiciye özgü bir şey yapmasını beklerdim.
gbulmer

@gbulmer: Doğru C programında bir dize değişmezini değiştiremezsiniz. Ne deneyen yanlış bir C programı ne burada ne de orada.
caf

@gbulmer: Yararlı bir tanım, C dili standardında belirtilen herhangi bir kısıtlamayı kırmayan bir programdır. Başka bir deyişle, bir dize değişmez değerini değiştiren bir program, boş bir işaretçiyi dereferences veya 0 ile bir bölme gerçekleştirenle aynı şekilde yanlıştır.
caf

caf - Kastettiğin bu olabileceğini düşündüm. Sonra "Her iki durumda da bir dize değişmez değeri değiştiremezsiniz" bunu belirtiyor gibi görünüyor. "Her iki durumda da C dili standardında belirtilen kısıtlamalar ne olursa olsun bozuldu ... Derleyici veya çalışma süresi sisteminin her durumda standardın ihlallerini tanımlaması mümkün değil." Ben standart etkisinin tanımsız olduğu pozisyon alır varsayalım?
gbulmer

1
Bir standart her iki şekilde de bir şey iddia edemediğinde, davranışı 'tanımsız' olarak tanımlamanın tam olarak doğru sınır ve yararlı olduğunu düşünüyorum. İlişkiyi ileri sürmek için, 'doğru C programı' ' boş göstericiyi kaldıramaz ' durma problemini kanıtlamaya eşdeğerdir. Ama umrumda değil. Ben bunu yapmaz ve onunla 'scott ücretsiz' kurtulmak için bekliyoruz :-)
gbulmer

4

DAVA 1:

char *str = "Hello";
str[0] = 'M'  //Warning may be issued by compiler, and will cause segmentation fault upon running the programme

Yukarıdaki ayarlar, programın ikili görüntüsünde sabit olarak kodlanmış ve bellekte salt okunur olarak işaretlenen "Hello" değişmez değerine işaret etmek için, bu String değişmezindeki herhangi bir değişikliğin geçersiz olduğu ve segmentasyon hataları oluşturacağı anlamına gelir.

DURUM 2:

const char *str = "Hello";
str[0] = 'M'  //Compile time error

DURUM 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".

2

İlk olarak gerçekten değiştirebiliyorsanız, ikinci olarak değiştiremezsiniz. Hakkında kadar okuyun const(fark hakkında bazı güzel kılavuzları var) doğruluğu. Ayrıca char const * nameonu yeniden işaretleyemeyeceğiniz yer de var.


Tam olarak ne değişebilir?
Antti Haapala

2

Soru, arasındaki fark nedir

char *name

sabit dize değişmezine işaret eder ve

const char *cname

Verildi

char *name = "foo";

ve

const char *cname = "foo";

2 arasında çok fazla fark yoktur ve her ikisi de doğru olarak görülebilir. Nedeniyle C kodunun uzun mirasına, dize hazır bir tür oldu char[]değil, const char[]ve aynı şekilde kabul ettiklerini eski kod sürü char *yerineconst char * onlar argümanları değiştirmek olmadığında bile.

Genel olarak 2 temel fark olduğunu *cnameveya cname[n]Çeşidi Sol taraf değerlendirecek const charise, *nameya da name[n]Çeşidi Sol taraf değerlendirecek charolan, değiştirilebilir Sol taraf . Atamanın hedefi değiştirilebilir bir değer değilse, bir tanılama mesajı üretmek için uygun bir derleyici gerekir ; aşağıdaki değerlere tahsis konusunda herhangi bir uyarı oluşturmasına gerek yoktur char:

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

Her iki durumda da derleyicinin derlemeyi durdurması gerekmez ; görevlendirme için bir uyarı oluşturması yeterlidir cname[0]. Ortaya çıkan program doğru bir program değil . Yapının davranışı tanımlanmamıştır . Çökebilir veya daha da kötüsü çökmeyebilir ve bellekteki dize değişmezini değiştirebilir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.