2016-11-16 14 views
1

Я не уверен, что это нормально или это ошибка компилятора, но у меня есть C-структура с множеством членов. Среди них, есть,:Как сказать gcc отключить заполнение внутри структуры?

struct list { 
    ... 
    ... 
    const unsigned char nop=0x90; // 27 bytes since the begining of the structure 
    const unsigned char jump=0xeb; // 28 bytes since the begining of the structure 
    const unsigned char hlt=0xf4; // 29 bytes since the begining of the structure 
    unsigned __int128 i=0xeb90eb90eb90eb90f4f4 // should start at the 30th byte, but get aligned on a 16 byte boundary and starts on the 32th byte instead 
    const unsigned char data=0x66; // should start at the 46th byte, but start on the 48th instead. 
}; // end of struct list. 

У меня было трудное время, чтобы выяснить, почему моя программа не работала, но я наконец-то нашел есть зазор 2 байта между hlt и i, который установлен в 0x0 , Это означает, что i выравнивается.
Это очень ясно, когда я PRINTF той части структуры, так как с:

for(int i=28;i<35;i++) 
    printf("%02hhX",buf[i]); 

я EBF40000EB90EB90 на экране.

Я пробовал такие вещи, как volatile struct list data; в моей программе, но это не изменило проблему выравнивания.

Значит, есть #pragma или __attribute__, чтобы сообщить gcc, чтобы не выровнять i внутри struct list?

+0

Это похоже на синтаксическую ошибку для меня. Это C++ или что-то еще? – melpomene

+0

Это не ошибка. В C каждый член структуры может иметь неопределенное дополнение после него. Почему это проблема? – melpomene

+0

Посмотрите на '#pragma pack (1)', но убедитесь, что это то, что вам действительно нужно и чего хочет. – Banex

ответ

11

В GCC вы можете использовать __attribute__((packed)) так:

// sizeof(x) == 8 
struct x 
{ 
    char x; 
    int a; 
}; 

// sizeof(y) == 5 
struct y 
{ 
    char x; 
    int a; 
} __attribute__((packed)); 

См doc.

Также, если вы полагаетесь на адреса структурных полей, взгляните на макрос offsetof. Возможно, вам не нужно упаковывать структуру вообще.

+0

Возможно, вместо '__attribute__ ((__packed __))' вместо? – GReaperEx

+0

@MichaelPetch: наконец, проблема: атрибут был правильным заклинанием на моем языке. Извините за автоматическую ошибку проверки орфографии. – user2284570

2

Поля в пределах struct дополняются определенным образом.

Считается, что поля обычно выровнены по офису, который является кратным размеру элемента данных (или элемента массива, если элемент является массивом), о котором идет речь. Таким образом, 16-битное поле начинается с смещения 2 байта, 32-битное поле начинается с 4-байтового смещения и т. Д.

Если вы переупорядочиваете поля в своем struct, чтобы придерживаться этого руководства, обычно вы можете избежать наличия внутренних прокладок в пределах struct (хотя в конечном итоге вы можете получить некоторую дополнительную прокладку).

Положив поля на надлежащее смещение, можно добиться повышения производительности за сильную упаковку struct.

Для получения дополнительной информации см. this article on structure packing.

Использование этих технологий не гарантируется, они, как правило, работают в большинстве случаев.

+0

Я подозреваю в использовании в вопросе OPs, что переупорядочение не является допустимым вариантом, так как он использует структуру для хранения машинных инструкций. В его случае прямой способ разрешить упаковку (до 1 байт) - лучший вариант ИМХО. –

+0

@MichaelPetch: Да, и цель моей структуры состоит в том, чтобы получить 'i' пересечение границы 32 байта. – user2284570

3

Как затрагивали от @Banex

#pragma pack(push,1) 
struct 
{ 
     char a; 
     int b; 
     long long c; 
} foo; 
#pragma pack(pop) 

#pragma pack(push,1) выталкивает текущий режим упаковки внутри и наборы упаковка 1, не отступы

#pragma pack(pop) восстанавливает предыдущее УПАКОВКИ

Возможно, совместимые с синтаксисом Microsoft

http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html