В чем смысл "__attribute __ ((упакованный, выровненный (4)))"

Это язык C. Это написано, что:

typedef struct __attribute__((packed, aligned(4))) Ball {
    float2 delta;
    float2 position;
    //float3 color;
    float size;
    //int arcID;
    //float arcStr;
} Ball_t;
Ball_t *balls;

Скажите, пожалуйста, что это значит, и как использовать это ключевое слово.

Ответ 1

Прежде чем ответить, я хотел бы дать вам некоторые данные из Вики


Выравнивание структуры данных - это способ упорядочения и доступа к данным в памяти компьютера. Он состоит из двух отдельных, но связанных вопросов: выравнивание данных и заполнение структуры данных.

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

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


gcc предоставляет функциональность для отключения заполнения структуры. то есть, чтобы избежать этих бессмысленных байтов в некоторых случаях. Рассмотрим следующую структуру:

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}sSampleStruct;

sizeof(sSampleStruct) будет 12, а не 8. Из-за заполнения структуры. По умолчанию в X86 структуры будут дополнены 4-байтовым выравниванием:

typedef struct
{
     char Data1;
     //3-Bytes Added here.
     int Data2;
     unsigned short Data3;
     char Data4;
     //1-byte Added here.

}sSampleStruct;

Мы можем использовать __attribute__((packed, aligned(X))), чтобы настаивать на заполнении определенного (X) размера. Х должен быть степенью двойки. См. здесь.

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}__attribute__((packed, aligned(1))) sSampleStruct;  

поэтому указанный выше атрибут gcc не допускает заполнение структуры. поэтому размер будет 8 байтов.

Если вы хотите сделать то же самое для всех структур, просто мы можем поместить значение выравнивания в стек, используя #pragma

#pragma pack(push, 1)

//Structure 1
......

//Structure 2
......

#pragma pack(pop)

Ответ 2

  • packed означает, что он будет использовать минимально возможное пространство для struct Ball - то есть он будет копировать поля вместе без заполнения
  • aligned означает, что каждый struct Ball будет начинаться с 4-байтовой границы - т.е. для любого struct Ball, его адрес можно разделить на 4

Это расширения GCC, а не часть любого стандарта C.

Ответ 3

Атрибут packed означает, что компилятор не будет добавлять отступы между полями struct. Заполнение обычно используется, чтобы поля совпадали с их естественным размером, потому что некоторые архитектуры налагают штрафы за несвязанный доступ или вообще не допускают его.

aligned(4) означает, что структура должна быть выровнена по адресу, который делится на 4.