2013-08-13 1 views
2

Следующий код;Структуры в 32-битной архитектуре

struct s1 { 
    void *a; 
    char b[2]; 
    int c; 
}; 

struct s2 { 
    void *a; 
    char b[2]; 
    int c; 
}__attribute__((packed)); 

, если s1 имеет размер 12 байт и s2 имеет размер 10 байт, это из-за данных считываются в 4-байтовых куски и }__attribute__((packed)); уменьшает размер void*a; только 2 байта?

Немного смущенный относительно того, что }__attribute__((packed));.

Большое спасибо

ответ

5

Это связано с alignment, процесс, в котором компилятор добавляет скрытые «мусор» между полями, чтобы убедиться, что они имеют оптимальные (по производительности), начиная с адреса.

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

+0

это также может врезаться (в зависимости от оборудования). –

+0

@TomTanner Doh, конечно. Спасибо, я редактировал. – unwind

0

Это связано с data structure alignment, сочетанием двух процессов: выравнивания данных и заполнения данных. Первая структура будет выровнена со словом, как вы сказали, однако вторая структура упакована и заставляет компилятор не помещать структуру в слово.

Вторая структура - 10 байт, потому что массив символов равен 2 байтам, не указатель на void (он остается 4 байта, как и все указатели). Это может помешать производительности, поскольку компромисс между двумя байтами пространства не стоит эффективности, утраченной аппаратным обеспечением (в большинстве случаев) и может привести к неопределенному поведению.

+1

"он остается 4 байта, так как все указатели" довольно широки. В настоящее время я работаю с C, где указатели - 2 байта и 4 байта. Также скомпилированы с 8-байтовыми указателями. – chux

+0

@chux, можете ли вы показать пример этого? Мне действительно интересно, почему это может произойти. –

+0

http://www.microchip.com/pagehandler/en-us/family/16bit/ Старые ПК DOS: в различных режимах были указатели данных 16/32 и независимо указатели на функции 16/32. Intel 64 бит http://www.intel.com/content/www/us/en/architecture-and-technology/microarchitecture/intel-64-architecture-general.html – chux

2

На процессорах Intel выборки 32-разрядных выровненных данных значительно быстрее, чем неровности; на многих других процессорах выровненные выборки могут быть незаконным вообще, или их нужно моделировать, используя 2 инструкции. Таким образом, первая структура будет иметь c всегда на этих 32-разрядных архитектурах, выровненных по байтовому адресу, делящемуся на 4. Это, однако, требует, чтобы 2 байта были потрачены впустую на хранение.

struct s1 { 
    void *a; 
    char b[2]; 
    int c; 
}; 

// Byte layout in memory (32-bit little-endian): 
// | a0 | a1 | a2 | a3 | b0 | b1 | NA | NA | c0 | c1 | c2 | c3 | 
// addresses increasing ====> 

С другой стороны, иногда вам абсолютно необходимо сопоставить некоторые невыровненные datastructures (например, форматы файлов или сетевых пакетов), как это, в структуры С; там вы можете использовать __attribute__((packed)), чтобы указать, что вы хотите все без отступа байт:

struct s2 { 
    void *a; 
    char b[2]; 
    int c; 
} __attribute__((packed)); 

// Byte layout in memory (32-bit little-endian): 
// | a0 | a1 | a2 | a3 | b0 | b1 | c0 | c1 | c2 | c3 | 
// addresses increasing ====> 
Смежные вопросы