Dlaczego konwersja ze stałej łańcuchowej na 'char*' jest prawidłowa w C, ale nieprawidłowa w C++

Standard C++11 (ISO/IEC 14882:2011) mówi w § C.1.1:

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

Dla C++ jest to OK, ponieważ wskaźnik do literału Łańcuchowego jest szkodliwy, ponieważ każda próba jego modyfikacji prowadzi do awarii. Ale dlaczego jest ważny w C?

C++11 says also:

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

Co oznacza, że jeśli Obsada zostanie dodana do pierwszego twierdzenia, staje się ważna.

Dlaczego casting sprawia, że druga instrukcja jest ważna w C++ i czym różni się od pierwszej? Czy to nie jest wciąż szkodliwe? Jeśli tak, to dlaczego standard powiedział, że jest OK?

Author: Vadim Kotov, 2014-01-06

4 answers

W C++03, twój pierwszy przykład był poprawny, ale użyto przestarzałej konwersji domyślnej-literał Łańcuchowy powinien być traktowany jako typ char const *, ponieważ nie można modyfikować jego zawartości (bez powodowania niezdefiniowanego zachowania).

Począwszy od C++11, domyślna konwersja, która została wycofana, została oficjalnie usunięta, więc kod, który od niej zależy (jak w Twoim pierwszym przykładzie), nie powinien już się kompilować.

Zauważyłeś jeden sposób, aby umożliwić kompilację kodu: chociaż Ukryty konwersja została usunięta, konwersja Jawna nadal działa, więc możesz dodać obsadę. Ja bym nie rozważał jednak to "naprawianie" kodu.

Naprawa kodu wymaga zmiany typu wskaźnika na właściwy typ:

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

Dlaczego było dozwolone w C++ (i nadal jest w C): po prostu dlatego, że jest dużo istniejącego kodu, który zależy od tej ukrytej konwersji, i łamanie tego kodu (przynajmniej bez jakiegoś oficjalnego Ostrzeżenia) najwyraźniej standardowe komitety uznały to za zły pomysł.

 240
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 07:12:11

Jest ważny w C ze względów historycznych. C tradycyjnie określał, że typ literału łańcuchowego to char *, a nie const char *, chociaż kwalifikował go mówiąc, że nie można go modyfikować.

Kiedy używasz cast, zasadniczo mówisz kompilatorowi, że znasz lepiej niż domyślne reguły dopasowywania typów, a to sprawia, że przypisanie jest OK.

 19
Author: Barmar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 07:10:31

Możesz również użyć strdup :

char* p = strdup("abc");
 3
Author: baz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-11 05:24:50

Możesz zadeklarować jako jedną z poniższych opcji:

char data[] = "Testing String";

Lub

const char* data = "Testing String";

Lub

char* data = (char*) "Testing String";
 0
Author: Shiv Buyya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-26 10:04:48