Standard C ++ 11 (ISO / IEC 14882: 2011) mówi w § C.1.1
:
char* p = "abc"; // valid in C, invalid in C++
W przypadku C ++ jest to w porządku, ponieważ wskaźnik do literału ciągu jest szkodliwy, ponieważ każda próba jego modyfikacji prowadzi do awarii. Ale dlaczego jest ważny w C?
C ++ 11 mówi również:
char* p = (char*)"abc"; // OK: cast added
Co oznacza, że jeśli rzut zostanie dodany do pierwszej instrukcji, stanie się ważny.
Dlaczego rzutowanie sprawia, że druga instrukcja jest ważna w C ++ i czym różni się od pierwszej? Czy to nadal nie jest szkodliwe? Jeśli tak, to dlaczego norma mówi, że jest OK?
char[]
w pierwszej kolejności. Drugi toconst_cast
w przebraniu.OK
.const
, więc niekoniecznie byłyconst
.Odpowiedzi:
Aż do C ++ 03, twój pierwszy przykład był prawidłowy, ale używał przestarzałej niejawnej konwersji - literał ciągu powinien być traktowany jako typ
char const *
, ponieważ nie możesz modyfikować jego zawartości (bez powodowania niezdefiniowanego zachowania).Począwszy od C ++ 11, niejawna konwersja, która była przestarzała, została oficjalnie usunięta, więc kod, który od niej zależy (jak Twój pierwszy przykład) nie powinien już się kompilować.
Zauważyłeś jeden sposób, aby zezwolić na kompilację kodu: chociaż niejawna konwersja została usunięta, jawna konwersja nadal działa, więc możesz dodać rzutowanie. Chciałbym nie , jednak należy wziąć pod uwagę tę „fixing” kod.
Prawidłowe naprawienie kodu wymaga zmiany typu wskaźnika na właściwy typ:
Co do tego, dlaczego było to dozwolone w C ++ (i nadal jest w C): po prostu dlatego, że istnieje wiele istniejącego kodu, który zależy od tej niejawnej konwersji, a złamanie tego kodu (przynajmniej bez oficjalnego ostrzeżenia) najwyraźniej wydawało się standardowym komitetom, takim jak zły pomysł.
źródło
char const *p = "abc";
jest „prawidłowy i bezpieczny zarówno w C i C ++”, a nie „prawidłowy i bezpieczny w obu C lub C ++”.Jest ważny w C z powodów historycznych. C tradycyjnie określał, że typ literału ciągu to
char *
raczej niżconst char *
, chociaż kwalifikował go, mówiąc, że w rzeczywistości nie możesz go modyfikować.Kiedy używasz rzutowania, zasadniczo mówisz kompilatorowi, że wiesz lepiej niż domyślne reguły dopasowywania typów, i sprawia, że przypisanie jest OK.
źródło
char[N]
i został zmieniony naconst char[N]
. Zawiera informacje o rozmiarze.char[N]
ale nie jestchar*
np."abc"
char[4]
Możesz także użyć strdup :
źródło