Введение
Унарный оператор
`sizeof` — это унарный оператор в языках программирования C и C++. Он определяет размер в памяти выражения или типа данных, измеряемый в количестве единиц размера `char`. Следовательно, конструкция `sizeof(char)` гарантированно равна 1. Фактическое количество бит в типе `char` определяется макросом препроцессора, определённым в стандартном заголовочном файле `limits.h`. На большинстве современных вычислительных платформ это восемь бит. Результат `sizeof` имеет тип беззнакового целого числа, обычно обозначаемый как `size_t`.
Оператор имеет единственный операнд, который может быть либо выражением, либо приведением типа данных, представленным типом данных в скобках. Типы данных могут быть не только примитивными, такими как целочисленные и типы с плавающей точкой, но также и указателями, а также составными типами данных (объединениями, структурами и классами C++).
Неполные типы
sizeof может применяться только к "полностью" определенным типам. Для массивов это означает, что размеры массива должны быть указаны в его объявлении, и что тип элементов должен быть полностью определен. Для структур и объединений это означает, что должен быть список членов полностью определенных типов. Например, рассмотрим следующие два исходных файла: оба файла являются совершенно корректными в C, и код в них может применять sizeof к `arr` и `s`. Однако, для кода в другом файле это недопустимо, поскольку определения в первом файле неполны. В случае `arr`, код не указывает размер массива; без этой информации компилятор не может узнать, сколько элементов в массиве, и не может рассчитать общий размер массива. Аналогично, компилятор не может рассчитать размер `s`, потому что он не знает, из каких членов она состоит, и, следовательно, не может рассчитать сумму размеров членов структуры (и выравнивания). Если программист указал размер массива в его объявлении в первом файле, или завершил определение `s`, предоставив список членов, это позволило бы применить sizeof к `arr` или `s` в этом исходном файле.
Both files are perfectly legal C, and code in can apply sizeof to arr and However, it is illegal for code in to do this, because the definitions in are not complete. In the case of arr, the code does not specify the dimension of the array; without this information, the compiler has no way of knowing how many elements are in the array, and cannot calculate the array's overall size. Likewise, the compiler cannot calculate the size of because it does not know what members it is made up of, and therefore cannot calculate the sum of the sizes of the structure's members (and padding). If the programmer provided the size of the array in its declaration in , or completed the definition of by supplying a member list, this would allow the application of sizeof to arr or in that source file.
Члены объекта
C++11 предоставил возможность применения оператора sizeof к конкретным членам класса без необходимости создания экземпляра объекта для этого. Например, следующий пример выдает и на большинстве платформ.
Пакеты с различными шаблонами
C++11 представил вариативные шаблоны; ключевое слово `sizeof`, за которым следует многоточие, возвращает число элементов в параметрическом пакете.
Реализация
При применении к типу данных фиксированной длины или переменной, выражения с оператором `sizeof` вычисляются во время компиляции программы и заменяются на константные значения. Стандарт C99 представил массивы переменной длины (VLA), что потребовало вычисления таких выражений во время выполнения программы. Во многих случаях особенности реализации могут быть задокументированы в документе ABI (Application Binary Interface) для платформы, определяющем форматы, дополнения и выравнивание типов данных, которым компилятор должен соответствовать.
Покрытие конструкции
При расчете размера любого типа объекта компилятор должен учитывать необходимое выравнивание структуры данных для обеспечения эффективности или соответствия архитектурным ограничениям. Многие компьютерные архитектуры не поддерживают доступ к нескольким байтам, начиная с адреса, не кратного размеру слова, и даже если архитектура это позволяет, процессор обычно быстрее извлекает объект, выровненный по границе слова, чем объект, занимающий несколько слов в памяти. Поэтому компиляторы обычно выравнивают структуры данных как минимум по границе слова, а также выравнивают отдельные члены по их соответствующим границам. В следующем примере структура `student` скорее всего будет выровнена по границе слова, которая также является началом члена `grade`, а член `age` скорее всего начнется со следующего адреса слова. Компилятор добивается этого, вставляя байты заполнения между членами по мере необходимости для удовлетворения требованиям выравнивания. В конце структуры также может быть добавлено заполнение для обеспечения правильного выравнивания, если структура используется в качестве элемента массива. Таким образом, общий размер структуры в C может превышать сумму размеров ее отдельных членов. Например, на многих системах следующий код выводит: