Что означает «__attribute __ ((упаковано, выровнено (4)))»

122

Это язык 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;

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

Аарон Ли
источник
4
Это «атрибут типа» ... (я нашел это с помощью «упакованного атрибута C» в Google. Конечно, другие могут, по крайней мере, сделать так же хорошо!)
1
Посмотрите на этот вопрос - хотя aligned(4), возможно, вам не о чем беспокоиться.
Кейт Томпсон

Ответы:

157

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


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

Когда современный компьютер читает или записывает в адрес памяти, он будет делать это фрагментами размером со слово (например, 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). 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)
Jeyaram
источник
6
Если память хранит данные в 4-байтовых фрагментах, то почему бы не добавить 2 байта заполнения к беззнаковому короткому значению (его 2 байта)? или компилятор просто добавляет байты заполнения к 1-му и последнему членам структуры? не могли бы вы прояснить это.
Пользователь
5
@User Plz тоже ссылается. Если вы все еще не
поняли, пожалуйста
Кто бы ни сказал, что эти заполняющие байты бессмысленны, тот не знает, что неправильный доступ к данным является странностью архитектуры x86. Эти байты необходимы, чтобы избежать исключений, когда процессор пытается загрузить - скажем целое число - данные, которые выходят за его естественную границу выравнивания.
Tanveer Badar
86
  • packedозначает, что он будет использовать наименьшее возможное пространство для struct Ball- т.е. он будет собирать поля вместе без заполнения
  • alignedозначает, что каждый struct Ballбудет начинаться с 4-байтовой границы - то есть для любого struct Ballадреса его можно разделить на 4

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

cnicutar
источник
17

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

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

Юлиан Стеклина
источник