Постоянные данные в стеке?

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

Передайте char* непосредственно в 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

это трейн 3

Это строка 4

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

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

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 был «только для чтения», если я только что написал в него.

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

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


person Bwebb    schedule 31.10.2018    source источник
comment
Вы говорите, что ожидаете, что компилятор выдаст предупреждение, когда вы передаете неконстанту, где ожидается константа?   -  person John3136    schedule 31.10.2018
comment
@ John3136 Да, я этого и ожидал.   -  person Bwebb    schedule 31.10.2018


Ответы (1)


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

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

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

person rici    schedule 31.10.2018
comment
Спасибо за разъяснение. Я уже принял ваш ответ, так как он имел смысл, но у вас есть ссылка, где я могу узнать об этом больше? - person Bwebb; 31.10.2018
comment
@bwebb: Любой хороший текст по программированию на C :) (Но не K, это слишком старо.) - person rici; 31.10.2018
comment
Сказав это, у меня нет никаких рекомендаций. Прости. - person rici; 31.10.2018