C中的默认联合和结构对齐?

时间:2015-10-08 14:12:27

标签: c memory-alignment

作为联合或结构的全局变量的默认对齐方式是什么。它们是否保证是字对齐的?特别是在使用GCC和SDCC时。

在代码中,函数f()是安全的,还是会导致未对齐的访问? 16位和32位平台之间有区别吗?

#define ADDR_SIZE 8

typedef union {
   unsigned char u8[ADDR_SIZE];
} addr_t;

addr_t global_address;

void f(void) {
   uint32_t x = *((uint32_t *)&global_address) + *((uint32_t *)&global_address + 1);
}

2 个答案:

答案 0 :(得分:1)

除非您使用例如__attribute__((aligned(4)))指定了对齐要求,否则无法保证联合正确对齐。

使用char进行仔细的全局变量排列,如下所示:

...
#define ADDR_SIZE 8

typedef union {
   unsigned char u8[ADDR_SIZE];
} addr_t;

addr_t global_address1;
char padd1;
addr_t global_address2;
addr_t global_address3;
...

你可以see这里有奇怪的地址:

0x804971d * &global_address1
0x8049714
0x8049715 * &global_address2
0x804970c

尝试在具有严格对齐要求的某些体系结构中访问这些地址将导致一些未对齐的访问异常并暂停程序。其他能够以性能成本处理错位访问的架构至少需要两个内存读取周期,这需要大量的CPU周期才能完成。

答案 1 :(得分:1)

  

作为联合或结构的全局变量的默认对齐方式是什么。

这取决于工会成员。

  

它们是否保证字对齐?

没有。 (假设单词是4字节)。对齐要求很复杂。虽然它们很少大于sizeof(int),但每种类型可能会有所不同。

在C11中,通过包含max_align_t对象,联合将根据需要与任何类型对齐。

  

max_align_t这是一种对象类型,其对齐方式与所有上下文中的实现所支持的一致; C11§7.192

#include <stddef.h>

typedef union {
   max_align_t dummy;
   unsigned char u8[ADDR_SIZE];
} addr_t;

@Jens Gustedt有关于别名的好处。只需从联盟中访问uint32_t即可。注意endian问题。

typedef union {
   unsigned char u8[ADDR_SIZE];
   uint32_t u32[ADDR_SIZE/sizeof(uint32_t)];
} addr_t;