2013-04-28 3 views
0

Мой плохой! Я предположил, что следующий отрывок из печально известной, но дико популярной книги полностью действителен . Но только сегодня мне было указано, что он ездил с UB (хотя я еще не нашел, как это происходит). Вот этот конкретный раздел из книги. Вы будете делать мне и многим другим «жертвам», как я отличный если вы можете указать в нумерованном порядке, что не так, или UB с каждым конкретным заявлением, и соответствующие исправления для них.Что не так в этих 5 бесчисленных способах декларирования/инициализации постоянных указателей? (Взято из сомнительной, но популярной книги)

char *p = "Hello" ; /* pointer is variable, so is string */ 
*p = 'M' ; /* works */ 
p = "Bye" ; /* works */ 


const char *q = "Hello" ; /* string is fixed pointer is not */ 
*q = 'M' ; /* error */ 
q = "Bye" ; /* works */ 


char const *s = "Hello" ; /* string is fixed pointer is not */ 
*s = 'M' ; /* error */ 
s = "Bye" ; /* works */ 


char * const t = "Hello" ; /* pointer is fixed string is not */ 
*t = 'M' ; /* works */  
t = "Bye" ; /* error */ 


const char * const u = "Hello" ; /* string is fixed so is pointer */ 
*u = 'M' ; /* error */ 
u = "Bye" ; /* error */ 
+1

'символ * p' должен указывать на неконстантного строки. Строковые литералы - это константы. – Elazar

+1

Приведенные выше случаи 'q' и' s 'идентичны. 'const char *' и 'char const *' являются одним и тем же типом. – Mat

+0

@mat Мне и другим нравится мне настоящая услуга. Потратьте минутку, чтобы опубликовать подробный ответ. –

ответ

1
char *p = "Hello" 

«Здравствуйте» строковый литерал помещается в реализации только для чтения памяти и изменить его любым возможным способом является UB. Независимо от того, где вы помещаете квалификатор const, любая попытка изменить строковый литерал - это UB. Правильный способ представить это в C++ является:

const char *p = "Hello"; 

char *p = "Hello" ; 

Указатель может быть желание пересесть, но строка не должна быть изменена.

const char *q = "Hello" ; 
char const *s = "Hello" ; 

Правильный способ представления указателя, указывающего на строковый литерал в C++. Указатель можно переустановить, но строка не должна изменяться.

char * const t = "Hello" ; 

Указатель не может быть переустановлен, и строка не должна изменяться.

const char * const u = "Hello" ; 

Указатель постоянный, поэтому строка.

Любая попытка изменить строку в любом из них - это UB.

+0

Поскольку вопрос отмечен C и не помечен C++, не должен ли этот ответ описывать ситуацию на C, а не то, что правильно в C++? (традиционный ответ на этот вопрос заключается в том, что C и C++ почти одинаковы для подмножества C на C++. Ну, если они одинаковы, можно было бы объяснить ситуацию в C. Плюс этот конкретный вопрос включает строковые литералы и литералы символов , оба из которых имеют разные типы в C и на C++) –

+0

@PascalCuoq Я собираюсь просверлить все, что сказал Алок в моей голове. Если вы чувствуете, что что-то о том, что он сказал, отличается от C, можете ли вы любезно сказать это в ответ? –

+0

@ Rüppell'sVulture http://stackoverflow.com/a/2245983/139746 –

1

Эти два случая неопределенное поведение:

char *p = "Hello" ; 
*p = 'M' ; // Undefined behavior: trying to modify a string literal. 


char * const t = "Hello" ; 
*t = 'M' ; // Undefined behavior: trying to modify a string literal. 
Смежные вопросы