C: Использование указателя char * const

67
7

В следующей программе p объявляется как указатель (который является постоянным, но строка не является). Но все же программа не работает и резко останавливается, говоря, что "untitled2.exe перестала работать".

#include<stdio.h>
#include<stdlib.h>

int main(){
char * const p = "hello";
*p = 'm';
return 0;
}

Почему это неожиданное поведение?

спросил(а) 2013-06-17T03:55:00+04:00 7 лет назад
1
Решение
94

Хотя сам p является указателем на объект const non- const, он указывает на строковый литерал. Строковый литерал - это объект, который, хотя и не const -qualified в отношении его типа, является неизменным.

Другими словами, p указывает на объект, который не является const, но ведет себя так, как если бы он был.

Подробнее об ANSI/ISO 9899: 1990 (C90), раздел 6.1.4.

ответил(а) 2013-06-17T06:33:00+04:00 7 лет назад
93

Вы получаете ошибку Windows, потому что вы неправомерно обращаетесь к памяти. В других системах вы можете получить SEGFAULT или SEGV или ошибку шины.

*p = 'm';

Пытается изменить первую букву постоянной строки "привет" от "h" до "m";

ответил(а) 2013-06-17T03:58:00+04:00 7 лет назад
68

char * const p = "hello";

определяет постоянный указатель p и инициализирует его адресом памяти постоянной строки "hello" которая по своей сути относится к типу const char *. По этому назначению вы отбрасываете спецификатор const. Он действителен C, но приведет к неопределенному поведению, если вы не знаете, что делаете.

Имейте в виду, что const char * запрещает вам изменять содержимое указываемой памяти, но не запрещает изменять адрес, в то время как char * const позволяет вам изменять содержимое, но исправляет адрес. Существует также комбо версия const char * const.

Хотя это действительный код C, в зависимости от места размещения ОС и ограничений на "hello" он может быть или не быть в записываемой памяти. Это остается неопределенным. Как правило, на большом пальце: константные строки являются частью исполняемого текста программы и доступны только для чтения. Таким образом, попытка записи на *p дает вам ошибку разрешения памяти SIGSEGV.

Правильный способ - скопировать содержимое строки в стек и работать там:

char p[] = "hello";

Теперь вы можете изменить *p потому что он находится в стеке, который читается/записывается. Если вам требуется то же самое глобально, то переведите его в глобальную область.

ответил(а) 2013-06-17T13:39:00+04:00 7 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема