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

Требует ли стандарт C размер массива из n элементов в n раз больше размера элемента?

Требуется ли стандарту C, чтобы размер массива из n элементов был в n раз больше размера элемента, либо явным выражением, либо строгим логическим выводом из его требований?

Например, может ли int (*x)[5] = malloc(5 * sizeof **x); не запрашивать достаточное пространство для массива из пяти int?

C 2011 [N1570] 6.5.3.4 7 показан пример вычисления количества элементов в массиве как sizeof array / sizeof array[0]. Однако примеры не являются нормативной частью стандарта (в параграфе 8 форварда).

6.2.5 20 говорит, что тип массива описывает смежно распределенный непустой набор объектов с определенным типом, но не говорит о полной требуемой памяти.

Это вопрос только на языке-юристе; фактические реализации не имеют значения. (Чтобы успокоить тех, кто хочет конкретных примеров, предположите реализацию C, которая требует дополнительного управления памятью для больших массивов, поэтому для создания массива требуется создание некоторых дополнительных данных для управления памятью.)

4b9b3361

Ответ 1

Единственный текст, описывающий представление массивов, довольно краток и находится в том, что вы нашли в 6.2.5 ¶20:

Любое число производных типов может быть построено из объектов и типов функций следующим образом:

  • Тип массива описывает смежно выделенный непустой набор объектов с конкретным типом объекта-члена, называемый типом элемента. Тип элемента должен быть полным всякий раз, когда задан тип массива. Типы массивов характеризуются их типом элемента и количеством элементов в массиве. Тип массива называется производным от его типа элемента, и если его тип элемента равен T, тип массива иногда называют "массивом T". Конструкция типа массива из типа элемента называется "выводом типа массива".

Обратите внимание, что он не говорит что-то вроде "смежно выделенного непустого набора объектов и дополнений", поэтому массив есть только объекты. Таким образом, нет никаких оснований для утверждения о том, что sizeof массив [type] может давать любой результат, отличный от размера смежного набора объектов, что, очевидно, N умножает размер отдельного типа элемента.

Также стоит отметить, что заполнение не является чем-то, что может просто существовать самостоятельно, потому что оно не указано, что оно не существует. C указывает представления типов (6.2.6) и явно указывает возможность заполнения битов и байтов, где это необходимо. Нет текста о заполнении массивов и, следовательно, он не является частью их представления.

Ответ 2

Да, требуется, чтобы размер массива T[n] был n * sizeof (T).

Стандарт определяет массивы в §6.2.5/20:

Тип массива описывает смежно выделенный непустой набор объектов с конкретным типом объекта-члена....

Кроме того, оператор sizeof дает общее количество байтов в массиве (§6.5.3.4/4):

Когда применяется sizeof.... к операнду, который имеет тип массива, результатом является общее количество байтов в массиве. При применении к операнду, который имеет структуру или тип объединения, результатом является общее количество байтов в таком объекте, включая внутреннее и конечное дополнение.

Так как массив состоит из смежного размещения объектов, внутреннее отступы не может быть. А так как конечное заполнение явно упоминается относительно оператора sizeof только в контексте объединений и структур, кажется очевидным, что массивы не будут иметь такого отступающего дополнения.

Наконец, обратите внимание, что в §6.2.6.1/4 указано:

Значения, хранящиеся в объектах без битового поля любого другого типа объекта, состоят из бит n x CHAR_BIT, где n - размер объекта этого типа, в байтах. Значение может быть скопировано в объект типа без знака char [n] (например, memcpy); результирующий набор байтов называется представлением объекта значения.

Предположим, что массивы могут иметь завершающие байты заполнения, рассмотреть массив unsigned char A[n] и дополнительно рассмотреть массив unsigned char B[sizeof A], к которому были скопированы все байты (включая возможные байты заполнения) A[]. Теперь A[] должен иметь тот же размер, что и B[], так как (§6.2.6.1/8):

Если оператор применяется к значению с более чем одним представлением объекта, то это представление объекта не влияет на значение результата.

Это означало бы, что B[] не должно иметь никакого отступающего дополнения, что означает, что массивы могут иметь завершающие байты заполнения, за исключением определенных особых условий, которые нигде не упоминаются в стандарте, или, альтернативно, что массивы могут иметь завершающее дополнение, за исключением массивов of unsigned char. Поскольку ни одна из этих возможностей не упоминается в стандарте, представляется разумным сделать вывод о том, что в первую очередь массивы не должны иметь прокрутки.