Ответ 1
Помимо детали возврата значения из функции, это как раз предмет Отчет о дефектах 222, представленный в 2000 году Клайвом Пером, и резолюция что DR, похоже, довольно четко отвечает на вопрос: возврат частично-неинициализированного struct
является корректным (хотя значения неинициализированных членов не могут использоваться.)
Разрешение DR подтвердило, что объекты struct
и union
не имеют ловушечных представлений (которые были явно добавлены в раздел 6.2.6.1/6). Следовательно, однонаправленное копирование не может использоваться в архитектуре, в которой отдельные члены могут попасть в ловушку. Хотя, предположительно, для синтаксического выражения, к стандарту не было добавлено явного утверждения об этом эффекте, сноска 42 (теперь сноска 51), которая ранее упоминала о возможности копирования по одному члену, была заменена гораздо более слабым утверждением, указывающим, что биты заполнения не должны скопированы.
Протоколы совещания WG14 (Торонто, октябрь 2000 г.) понятны (выделено мной):
DR222 - Частично инициализированные структуры
Этот DR задает вопрос о целесообразности назначения
struct
определяется, когда источником присвоения являетсяstruct
, некоторые из которых членам не дали значения. Был достигнут консенсус в отношении того, что это должен быть четко определен из-за общего использования, включая стандартную структуруstruct tm
. Был также достигнут консенсус, что если назначение с некоторыми членами, неинициализированными (и, возможно, с значение ловушки) было четко определено, в требуя, чтобы по крайней мере один член получил должное значение.
Поэтому понятие о том, что значение astruct
илиunion
в целом может имеют значение ловушки.
Интересно отметить, что в вышеуказанные минуты комитет считал, что даже не нужно, чтобы одному члену struct
была предоставлена ценность. Однако это требование впоследствии было восстановлено в некоторых случаях с разрешением DR338 (см. Ниже).
Вкратце:
-
Если автоматический агрегатный объект был хотя бы частично инициализирован или если его адрес был взят (тем самым он не подходит для объявления
register
в соответствии с разделом 6.3.2.1/2), тогда lvalue- to-rvalue для этого объекта хорошо определен. -
Такой объект может быть назначен другому агрегированному объекту того же типа, возможно, после его возврата из функции, без вызова поведения undefined.
-
Чтение неинициализированных членов в копии является либо undefined, либо неопределенным, в зависимости от того, возможны ли представления ловушки. (Чтение указателя на неподписанный тип узкого символа не может, например, захватить ловушку.) Но если вы напишете член перед его чтением, вы в порядке.
Я не верю, что существует теоретическая разница между назначением объектов union
и struct
. Очевидно, что union
не может быть скопирован членом членом (что бы это означало) и что тот факт, что какой-то неактивный член имеет ловушечное представление, не имеет значения, даже если этот элемент не сглажен ни одним другим элементом. Нет очевидной причины, почему struct
должен отличаться.
Наконец, что касается исключения из раздела 6.3.2.1/2: это было добавлено в результате разрешения DR 338. Суть этого DR заключается в том, что некоторое аппаратное обеспечение (IA64) может заманить использование неинициализированного значения в регистр. C99 не допускает представления ловушек для неподписанных символов. Таким образом, на таком оборудовании может оказаться невозможным поддерживать автоматическую переменную в регистре без "ненужного" инициализации регистра.
Резолюция DR 338 специально отмечает как поведение undefined использование неинициализированных значений в автоматических переменных, которые, возможно, могут храниться в регистрах (т.е. те, адрес которых никогда не был взят, как бы объявлен register
), таким образом позволяя компилятору сохранить автоматический unsigned char
в регистре, не беспокоясь о предыдущем содержимом этого регистра.
Как побочный эффект DR 338, кажется, что полностью неинициализированный автоматический struct
, адрес которого никогда не был принят, не может подвергаться преобразованию lvalue-to-rvalue. Я не знаю, был ли этот побочный эффект полностью рассмотрен в резолюции DR 338, но он не применяется в случае частично инициализированного struct
, как в этом вопросе.