Dize sabitinden 'char *' ya dönüştürme neden C için geçerli ancak C ++ için geçersiz


163

C ++ 11 Standardı (ISO / IEC 14882: 2011) şöyle diyor § C.1.1:

char* p = "abc"; // valid in C, invalid in C++

C ++ için, bir Dize Değişmezine bir işaretçi olarak zararlıdır, çünkü herhangi bir değişiklik denemesi çökmeye neden olur. Peki neden C'de geçerlidir?

C ++ 11 ayrıca şunları söylüyor:

char* p = (char*)"abc"; // OK: cast added

Bu, ilk ifadeye bir yayın eklenirse geçerli olacağı anlamına gelir.

Döküm neden ikinci ifadeyi C ++ 'da geçerli kılıyor ve birincisinden nasıl farklı? Hala zararlı değil mi? Durum buysa, standart neden iyi olduğunu söyledi?


3
C ++ 11 ilkine izin vermez. Neden C char[]ilk etapta bir dize değişmez türü yaptı bilmiyorum . İkincisi const_castkılık değiştirmiş.
chris

4
Bu kural değiştirilirse kırılacak çok fazla eski C kodu vardır.
Paul R

1
Lütfen Standardın ikincisinin söylediği metni belirtin OK.
Nawaz

13
C dili, daha önce dizgesel değişmezlere sahipti const, bu yüzden mutlaka değildi const.
Casey

2
C ve C ++ neredeyse her türden başka bir türe döküm yapmanıza izin verir. Bu, bu atmaların anlamlı ve güvenli olduğu anlamına gelmez.
Siyuan Ren

Yanıtlar:


207

C ++ 03'e kadar ilk örneğiniz geçerliydi, ancak kullanımdan kaldırılmış bir örtük dönüşüm kullandı - dize değişmezi tür olarak ele alınmalıdır char const *, çünkü içeriğini değiştiremezsiniz (tanımlanmamış davranışa neden olmadan).

C ++ 11'den itibaren, kullanımdan kaldırılan örtük dönüşüm resmi olarak kaldırıldı, bu nedenle ona bağımlı kod (ilk örneğiniz gibi) artık derlenmemelidir.

Kodun derlenmesine izin vermenin bir yolunu belirttiniz: örtük dönüşüm kaldırılmış olsa da, açık bir dönüşüm hala çalışıyor, böylece bir döküm ekleyebilirsiniz. Ben ediyorum değil ancak, bu "tespit" kodu düşünün.

Kodun tam olarak düzeltilmesi için işaretçinin türünün doğru türe değiştirilmesi gerekir:

char const *p = "abc"; // valid and safe in either C or C++.

Neden C ++ 'da izin verildiğine (ve hala C'de) gelince: sadece bu örtük dönüştürmeye bağlı olan mevcut kodun çok fazla olması ve bu kodu kırmanın (en azından resmi bir uyarı olmadan) görünüşte olduğu gibi standart komitelere göründüğü için Kötü bir fikir.


8
@rullof: En azından taşınabilirliğe önem veren kodlar için anlamlı bir esneklik vermeyecek kadar tehlikelidir. Bir dizgi hazır bilgisine yazmak genellikle programınızı modern bir işletim sisteminde iptal eder, bu nedenle kodun (yazmaya çalışmaya) izin vermesi anlamlı bir esneklik sağlamaz.
Jerry Coffin

3
Kod, bu cevapta verilen snippet'ine char const *p = "abc";"geçerli ve güvenli olduğunu hem C ve " geçerli ve güvenli C ++ "değil ya C ya da C ++".
Daniel Le

4
@DanielLe bu cümlelerin ikisi de aynı anlama sahiptir
Caleth

3
Oh Lordum! [Dili sıkıca yanağına yerleştirin] Üzgünüz, ama "veya" burada doğru terim. Kod C veya C ++ olarak derlenebilir, ancak aynı anda hem C hem de C ++ olarak derlenemez. İkisini de seçebilirsiniz, ancak bir seçim yapmanız gerekir. İkisine birden sahip olamazsınız. normal dil işlemine devam et.
Jerry Coffin

2
Hayır, hem / ve buradaki en açık ve en doğru ifadedir. Doğru anlamı iletmek için ya / ya da aynı zamanda olur, ancak teknik olarak açık değildir. Ya da tek başına kuşkusuz yanlıştır ( A veya B , A ve B'ye eşit değildir ).
Apollys, Monica

15

Tarihsel nedenlerle C'de geçerlidir. C, geleneksel olarak bir dizgi değişmezinin türünden char *ziyade const char *, gerçekten değiştirmenize izin verilmediğini söyleyerek nitelendirdiğini belirtmiştir.

Bir döküm kullandığınızda, derleyiciye varsayılan tür eşleme kurallarından daha iyi bildiğinizi söylersiniz ve atamayı tamamlar.


3
Bir char[N]ve değiştirildi const char[N]. Boyut bilgileri eklidir.
chris

1
C dize türüdür char[N]ama char*mesela "abc"olduğunuchar[4]
Grijesh Chauhan

2

Ayrıca strdup da kullanabilirsiniz :

char* p = strdup("abc");
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.