Стандартный раздел C11 6.2.5.20 определяет массив как:
Тип массива описывает непрерывно распределенный непустой набор объектов с конкретным типом объекта-члена, называемым типом элемента.
, в то время как структура определена как:
Тип структуры описывает последовательно распределенный непустой набор объектов-членов (и, при определенных обстоятельствах, неполный массив), каждый из которых имеет опциональноуказанное имя и, возможно, отдельный тип.
В разделе 6.7.2.1 говорится, что заполнение может быть вставлено между полями:
Каждый элемент не битового поля структуры илиобъект объединения выравнивается определенным реализацией способом, соответствующим его типу.
Внутри объекта структуры члены, не являющиеся битовыми полями, и блоки, в которых находятся битовые поля, имеют адреса, которые увеличиваются в порядке вкоторые они объявлены.Указатель на объект структуры, соответствующим образом преобразованный, указывает на его начальный элемент (или, если этот элемент является битовым полем, затем на модуль, в котором он находится), и наоборот.Внутри объекта структуры может быть безымянный отступ, но не в его начале.
Но означает ли это, что следующие объекты могут иметь разную структуру памяти?
struct A {
char x0;
short x1;
};
struct B {
struct A x0;
struct A x1;
struct A x2;
};
assert(sizeof(struct B) == sizeof(struct A[3]));
Iсоздал этот тестовый скрипт для проверки макета памяти для GCC:
import itertools
import subprocess
src = """
#include "assert.h"
struct A {
{fields}
};
struct B {
struct A x0;
struct A x1;
struct A x2;
};
int main(int argc, char** argv) {
assert(sizeof(struct B) == sizeof(struct A[3]));
return 0;
}
"""
def main():
all_types = ["char", "short", "int", "long long"]
for types in itertools.product(all_types, repeat=3):
rendered = src.replace("{fields}", "".join([
" {} x{};\n".format(t, i)
for i, t in enumerate(types)]))
with open("main.c", "w") as f:
f.write(rendered)
subprocess.call(["gcc", "main.c"])
subprocess.call(["./a.out"])
if __name__ == "__main__":
main()
Но GCC всегда создает одинаковую схему памяти для массива и структуры.
- Существуют ли примеры из реальной жизни, когда макет отличается?
- Безопасно ли приводить такой экземпляр структуры к массиву?
- Было бы безопаснее ссоюз?