Почему offsetof(member) равен sizeof(struct)?

У меня есть структура, определенная как:

struct smth
{
    char a;
    int b[];
};

Когда я звоню sizeof а также offsetof на этой структуре:

cout << sizeof(struct smth) << endl;
cout << offsetof(struct smth, b) << endl;

Выход:

4
4

Почему, когда размер элемента равен 4, а символ использует 1 байт, смещение массива int равно 4? Почему там какая-то набивка? Кроме того, почему массив int не занимает никакого места вообще?

3 ответа

Решение

Почему, когда размер элемента равен 4, а символ использует 1 байт, смещение массива int равно 4? Почему там какая-то набивка?

Есть отступы, потому что стандарт C позволяет это; Компилятор часто выравнивает переменные для повышения производительности.

Кроме того, почему вторая переменная не занимает никакого места вообще (что похоже на случай)?

Это член гибкого массива C99 - в этом весь смысл. Идея состоит в том, чтобы выделить вашу структуру примерно так:

struct smth *s = malloc(sizeof *s + 10 * sizeof s->b[0]);

И тогда у вас будет структура, которая работает как b были 10-элементный массив.

Потому что размер члена b равен нулю, и компилятор добавляет отступ между a а также b Члены так, что b находится на границе слова.

Однако, если я правильно помню, наличие гибкого массива в подобной структуре является допустимым только C, а не C++, кроме как в качестве расширения компилятора.

Поскольку OP комментирует, что вопрос в C++:

struct smth
{
    char a;
    int b[];
};

Массив как b[] недействителен в C++. Массив должен иметь фиксированный размер. Массивы переменной длины действительны только в C99.

Предполагая, что ваш компилятор поддерживает его как расширение, массив b[] имеет нулевой размер, что делает структуру, содержащую только char член. Правило заполнения в struct работает, дополняет struct к слову, которое составляет 4 байта в вашей машине.

Другие вопросы по тегам