Ответ 1
В параграфе C11 6.7.6.2p1 говорится:
Ограничения
- В дополнение к необязательным типам классификаторов и ключевому слову static,
[
и]
могут ограничивать выражение или *. Если они ограничивают выражение (которое задает размер массива), выражение должно иметь целочисленный тип. Если выражение является константным выражением, оно должно иметь значение больше нуля.
Поскольку ваша программа нарушает должна (0 не больше нуля), программа будет иметь поведение undefined, за исключением того, что в этом случае она появляется в пределах ограничений. Как говорится в разделе 4 Соответствие
4 Соответствие
В настоящем международном стандарте "должен" должен быть интерпретирован как требование для реализации или в программе; наоборот, "не должно" интерпретироваться как запрет.
Если требование '' should '' или 'не должно' ', которое появляется за пределами ограничения или ограничения времени выполнения, нарушается, поведение undefined. Поведение undefined иначе указано в этом Международном стандарте словами "поведение undefined" или отсутствием какого-либо явного определения поведения. В этих трех различиях нет разницы; все они описывают поведение "undefined".
Кроме того, 5.1.1.3p1 говорит:
- Соответствующая реализация должна содержать как минимум одно диагностическое сообщение (идентифицированное определенным образом), если блок перевода для предварительной обработки или блок перевода содержит нарушение любого синтаксиса правило или , даже если поведение также явно указано как undefined или определено для реализации. Диагностические сообщения не должны возникать при других обстоятельствах. [9])
С примечанием к сноске:
9) Цель состоит в том, чтобы реализация должна определять характер и, по возможности, локализовать каждое нарушение. Разумеется, реализация может свободно производить любое количество диагностических операций, пока действительная программа все еще правильно переводится. Он также может успешно преобразовать недопустимую программу.
Таким образом,
-
C11 не имеет массивов размера 0.
-
Наличие таких массивов является нарушением ограничения
-
Однако GCC позволяет массивы нулевого размера в качестве расширения
-
Соответствующая реализация C должна создавать диагностическое сообщение при таком использовании.
-
Этот GCC компилирует этот с настройками по умолчанию без вывода диагностического сообщения даже после установки
-std=c11
делаетgcc -std=c11
несоответствующей реализацией. -
[...], чтобы получить всю диагностику, требуемую стандартом, вы также должны указать
-pedantic
(или-pedantic-errors
, если вы хотите, чтобы они были ошибками, а не предупреждениями). -
Таким образом, чтобы использовать GCC для компиляции таким образом, чтобы он соответствовал стандарту C11, вы должны явно использовать не менее
gcc -std=c11 -pedantic
; и вы получите:zerosizearray.c:5:21: warning: ISO C forbids zero-size array ‘a’ [-Wpedantic] static char a[0];
-
Однако GCC по-прежнему будет компилировать вашу программу, даже если это некорректная программа (если вы не используете
-pedantic-errors
); в этом случае, естественно, не будет применяться ни один из требований стандарта.
Так как стандарт C фактически не разрешает объекты с нулевым размером (если я правильно прочитал, определение структуры должно также иметь по крайней мере один элемент и т.д.), и это больше того, что разные объекты должны занимать различное пространство в память, из которой происходят разные адреса для объектов; в стандарте ничего не указывается об адресах объектов размером 0.