размер союза больше, чем ожидалось.как здесь происходит выравнивание типов? - PullRequest
4 голосов
/ 10 декабря 2011
#include <stdio.h>

union u1 {
    struct {
        int *i;
    } s1;
    struct {
        int i, j;
    } s2;
};

union u2 {
    struct {
        int *i, j;
    } s1;
    struct {
        int i, j;
    } s2;
};

int main(void) {
    printf("        size of int: %zu\n", sizeof(int));
    printf("size of int pointer: %zu\n", sizeof(int *));
    printf("   size of union u1: %zu\n", sizeof(union u1));
    printf("   size of union u2: %zu\n", sizeof(union u2));
    return 0;
}

Результат:

$ gcc -O -Wall -Wextra -pedantic -std=c99 -o test test.c
$ ./test
        size of int: 4
size of int pointer: 8
   size of union u1: 8
   size of union u2: 16

Почему добавление целого числа 4 байта во вложенную структуру s1 объединения u2 увеличивает размер объединения в целом на 8 байтов?

Ответы [ 3 ]

8 голосов
/ 10 декабря 2011

Структура u2.s2 составляет 16 байтов из-за ограничений выравнивания. Компилятор гарантирует, что если вы создадите массив таких структур, каждый указатель будет выровнен по 8-байтовой границе. Поле *i занимает 8 байтов, затем j занимает 4 байта, и компилятор вставляет 4 байта заполнения. Поскольку структура составляет 16 байтов, объединение, содержащее ее, также составляет 16 байтов.

4 голосов
/ 10 декабря 2011

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

Таким образом, даже если вы добавите только 4 байта с дополнительными int, struct-alignment заставляет все быть выровненными до 8 байтов - отсюда +8, чтобы довести общий размер до 16 байтов.

Результат этого таков:

struct {
    int *i, j;
} s1;

имеет размер 16 байтов. Поскольку объединение должно быть не меньше, чем самый большой элемент, оно также увеличивается до 16.

http://en.wikipedia.org/wiki/Data_structure_alignment

2 голосов
/ 10 декабря 2011

Поскольку указатель составляет 8 байт на вашей платформе, он, скорее всего, также требует выравнивания 8 байт. Таким образом, при добавлении еще 4 байтов структура не может просто иметь размер 12 байтов, и в этом случае отдельные элементы, скажем, массива u2 s не будут должным образом выровнены по границам 8 байтов, что необходимо для члена указателя , Поэтому вам нужно увеличить его размер до следующего кратного 8, что равно 16. Дополнительные 4 байта просто не используются / не определены.

...