Подтвердить что ты не робот

Время жизни временных объектов в C11 и C99

Я пытаюсь расшифровать записку, которая привела к изменению между C99 и C11. Изменения, предложенные в этой записке, закончились в C11 6.2.4: 8, а именно:

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

Я понимаю, почему это изменение было необходимо (некоторые обсуждения можно найти здесь. Обратите внимание, что обсуждение продолжается до C11). Однако чего я не понимаю, так это побочного замечания, которое Кларк Нельсон сделал в своем письме:

Обратите внимание, что этот подход дополнительно объявляет пример, подобный этому, который соответствовал C99, как несоответствующий:

struct X { int a[5]; } f();
int *p = f().a;
printf("%p\n", p);

Я понимаю, почему этот пример не соответствует C11. Что я конкретно не понимаю, так это то, как это соответствует C99. И, если он определен в C99, что он должен делать, однозначно вывести значение висящего указателя?

4b9b3361

Ответ 1

Я понимаю, что на C99 самым тонким зерном жизни для объекта является блок. Таким образом, в то время как 6.5.2.2 (и некоторые другие §, упомянутые в примечании, к которому вы обращаетесь), конкретно говорит, что вы не можете получить доступ к возвращаемому значению после следующей точки последовательности, технически его адрес не неопределен, пока после того, как вы оставили закрывающий блок (причина, по которой вы должны иметь некоторое хранилище, зарезервированное для недоступного объекта, остается как упражнение для читателя). Таким образом, что-то вроде

struct X { int a[5]; } f();
int *p;
{ p = f().a; }
printf("%p\n", p);

составляет undefined в C99, а также в C11. В C11 понятие "временное время жизни", которое не существует на C99, позволяет считать, что указатель становится неопределенным, как только заканчивается полное выражение.