Почему это определение структуры добавляет дополнительный один байт использования памяти? - PullRequest
3 голосов
/ 16 марта 2012
#include <stdio.h>
typedef struct {
    short x,y;
    char type;
} Tile;

int main(int argc, const char *argv[])
{
    printf("%d\n",sizeof(short));
    printf("%d\n",sizeof(char));
    printf("%d\n",sizeof(Tile));
    return 0;
}

Вывод:

2
1
6

Я ожидал, что sizeof(Tile) будет 5 вместо 6. Это четко определенное поведение, которое добавляет один дополнительный байт использования памяти, илиэто зависит от реализации?

Ответы [ 4 ]

4 голосов
/ 16 марта 2012

Это из-за заполнения (вроде округления).

например:

struct example1
{
    char a;
    int b;
    char c;
}

struct example2
{
    char a;
    char b;
    int c;
}

, вероятно, будет различаться по размеру, первый будет иметь размер 12B, второй, скорее всего, будет использовать только 8B (в зависимости от арки и компилятора).

Редактировать: gcc выполняет заполнение по размеру самого большого члена структуры.

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

0 голосов
/ 16 марта 2012

Это не что иное, как структура padding. Я не думаю, что я должен объяснять, поскольку все другие ответы имеют достаточно информации.

Вы можете взглянуть на один из предыдущих вопросов: здесь

также есть хорошая вики для выравнивания структуры данных , которую очень полезно знать.

0 голосов
/ 16 марта 2012

Вы можете использовать следующий код для проверки заполнения структуры.

#include <stdio.h>

typedef struct {
    char a;
    int b;
    char c;
} Tile;

int main(int argc, const char *argv[])
{
    Tile tile;

    printf("%d %d %d\n", sizeof(int), sizeof(char), sizeof(tile));

    printf("%p\n", &tile.a);
    printf("%p\n", &tile.b);
    printf("%p\n", &tile.c);

    return 0;
}

Каждая переменная должна начинаться с относительного адреса, который можно разделить на размер этой переменной.Например, если есть переменная short, она должна начинаться с относительного адреса 0, 2, 4 ... и так далее.

0 голосов
/ 16 марта 2012

Мои эксперименты показывают, что структура выравнивается по 2-байтовой границе, так как в конце есть дополнительный байт заполнения.

Заполнение C зависит от реализации, и многие компиляторы даже позволяют вамизменить настройки выравнивания.Конкретное выравнивание не определено стандартом C.

Однако в x86_64 есть некоторые оптимизации для структур, которые влияют на это решение о заполнении, для небольших (<= 16 байт) структур они передаются через регистры,и наименьший регистр составляет 2 байта. </p>

Насколько я могу судить, большинство компиляторов C в большинстве случаев выравнивают по границам 4 байта, например, эта структура:

struct small {
    int x, y;
    char val;
}

10 байт.В то время как этот:

struct big {
    int x, y, z, w;
    char val;
}

равен 20 байтам.

И в clang, и в gcc структуры выровнены по 2-байтовым границам, когда они <= 16 байт, и выровнены по 4-байтовым границам, в противном случае. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...