Const данные в стеке? - PullRequest
       14

Const данные в стеке?

0 голосов
/ 31 октября 2018

Я собирался ответить на вопрос кого-нибудь о том, что printf принимает char *, поэтому я создал небольшую тестовую программу и у меня был свой вопрос. скомпилировано на codechef.com/ide с GCC 6.3

Передача символа * непосредственно в printf Я думаю, что вопросы спрашивают, что случилось с «отсутствующим» const, верно? http://man7.org/linux/man-pages/man3/printf.3.html

char * str1 = "This is string 1\n";
char str2[] = "This is string 2\n";
int main(void) {

    char str3[100] = "This is string 3\n";
    char * str4 = "This is string 4\n";

    str3[8] = 'c';

    printf(str1);
    printf(str2);
    printf(str3);
    printf(str4);

    return 0;
}

Выходы:

Это строка 1

Это строка 2

Это ctring 3

Это строка 4

Я рассматривал схему памяти программы, и я запутался еще больше. https://www.geeksforgeeks.org/memory-layout-of-c-program/

str1 - указатель на строковый литерал "это строка 1 \ n". str1 живет в данных и указывает на строковый литерал, который живет в ?? (я предполагал также инициализированный сегмент данных) Как реализована постоянная память в C?

str2 похож на str1 в плане разметки памяти.

str3, где это становится интересным. str3 живет в стеке, шириной 100 символов, и ему присваиваются значения char [0] = 'T', char [1] = 'h' и т. д. с объявлением / присваиванием. Это не должно быть постоянным. Объявление и присваивание str3 объявляют 100 символов в стеке и присваивают им значения из данных (либо сегмента данных, либо сегмента инициализированных данных, либо текста?).

str4 - указатель на стек, указывающий на память сегмента данных. Это как str1 и str2, не слишком интересно.

Затем присваивание str3 [8] = 'c' только для проверки / проверки / демонстрации того, что память стека для str3 НЕ доступна только для чтения перед печатью.

Я бы ожидал, что 1,2,4 будет работать, но почему работает 3 (даже предупреждение компилятора ???). Я, вероятно, ошибочно полагаю, что const является синонимом «только для чтения», потому что str3 не может быть «только для чтения», если я только что написал в него.

Есть ли в стеке постоянная память для переменной const, объявленной в функции?

Может кто-нибудь объяснить мне, почему str3 не выдал предупреждение или ошибку? str3 не является const char *, либо компилятор оптимизировал его (изменив назначение на «Это ctring 3 \ n»), либо предупреждения были подавлены (также маловероятно), либо у меня возникло фундаментальное неправильное понимание ключевого слова cost , Как стека памяти? Возможно, одно или несколько моих предположений неверны.

1 Ответ

0 голосов
/ 31 октября 2018

Когда прототип функции включает указатель на const -квалифицированный объект, это означает, что функция обещает не пытаться изменить указанное содержимое. Это не означает, что может быть принят только указатель на const объект (что бы это ни было).

С другой стороны, если в прототипе есть указатель на объект, который не const -квалифицирован, это означает, что он может пытаться изменить содержимое. В этом случае передача указателя на неизменяемый объект приведет к неопределенному поведению. Большинство компиляторов будут предупреждать вас, если вы попытаетесь передать указатель на const -квалифицированный объект (если вы включите предупреждения), поскольку const -квалифицированный указатель может указывать на неизменный объект.

Вообще говоря, вы должны рассматривать const в значении «я обещаю не изменять это», а не «это нельзя изменить».

...