2013-09-17 2 views
1

Если TStruct упакован, то этот код заканчивается на Str.D == 0x00223344 (не 0x11223344). Зачем? ARM GCC 4.7ARM GCC unaligned access

#include <string.h> 

typedef struct { 
    unsigned char B; 
    unsigned int D; 
} __attribute__ ((packed)) TStruct; 

volatile TStruct Str; 

int main(void) { 
    memset((void *)&Str, 0, sizeof(Str)); 
    Str.D = 0x11223344; 
    if(Str.D != 0x11223344) { 
    return 1; 
    } 
    return 0; 
} 
+0

'' __attribute__ ((упакованный)) 'упакованный, кажется, запустил этот код, поэтому я бы сказал, что это ошибка в gcc, хотя ошибка связана с тем, что' Str' является неустойчивым. – nos

+0

Если вы принудительно неравнозначные обращения к данной архитектуре, то вам лучше понять, как эта архитектура обрабатывает неуравновешенные нагрузки/хранилища. –

+0

@PaulR gcc исправит это в таких случаях. Он знает о выравнивании архитектуры и генерирует код для выполнения правильных операций с битами при аннотации структуры с упакованными данными, например. (хотя он не будет исправлять ситуацию, если вы попытаетесь сохранить/загрузить такую ​​структуру из, например, массива char). Очевидно, что добавление -fno-strict-volatile-bitfields будет «исправлять» код OP, но это сделает изменчивый классификатор сомнительной полезности – nos

ответ

0

Я думаю, что ваша проблема не имеет ничего общего с негласным доступом, но с определением структуры. int не обязательно длиной 32 бит. Согласно стандарту C, int имеет длину не менее 16 бит, а char имеет длину не менее 8 бит.

Моя догадка, Ваш компилятор оптимизирует TStruct так это выглядит следующим образом:

struct { 
    unsigned char B : 8; 
    unsigned int D : 24; 
} ...; 

При назначении 0x11223344 в Str.D, чем в соответствии со стандартом C, компилятор должен сделать только в том, что по крайней мере 16 бит (0x3344) записываются в Str.D. Вы не указали, что Str.D имеет длину 32 бит, только длина не менее 16 бит.

Ваш компилятор может также организовать-структуру, как это:

struct { 
    unsigned char B : 16; 
    unsigned int D : 16; 
} ...; 

B по меньшей мере, 8 бит в длину, и D длиной не менее 16 бит, все ок.

Возможно, что вы хотите сделать, это:

#include <stdint.h> 

typedef struct { 
    uint8_t B; 
    uint32_t D; 
} __attribute__((packed)) TStruct; 

Таким образом, можно обеспечить 32-битное значение 0x11223344 правильно пишет Str.D. Рекомендуется использовать типы с ограниченным размером для __packed structs.
Что касается неприсоединения доступа к члену внутри структуры, компилятор должен позаботиться об этом. Если компилятор знает определение структуры, то при обращении к Str.D он должен позаботиться о любых невыложенных операциях доступа и бит/байт.