将数组的起始地址对齐为32位的倍数?

时间:2017-07-18 15:03:18

标签: c arrays memory-management global

我有一个全局的数组类型的char。我希望起始地址与32位对齐。当我检查地图文件中的虚拟地址时,它是xxxxxx56H。如何将起始地址对齐为32位的倍数。我需要通用解决方案而不是编译器相关解我试过了

#pragma pack(32)
char array[223];
#pragma pack

但不行。

P.S:为了与32位对齐,最后两位地址应为0。

2 个答案:

答案 0 :(得分:1)

包装是完全不相关的。要对齐静态变量或结构成员(相对于struct start),请使用标准_Alignas specifier

如果您需要平台上的最大对齐(即适合任何类型的对齐),请使用max_align_t,对于特定的字节对齐,只需将对齐指定为常量表达式:

_Alignas(32 / CHAR_BIT) char a[10];

(如果除法有余数,这会导致问题;你真的是指32 或32 字节?标准不能保证一个字节有8位。)

如果您打算将数组强制转换为任何其他类型,则仍会通过违反有效类型(又称严格别名)规则来调用未定义的行为。对阵列使用正确的类型,并使用较大的类型对齐或任何您想要使用的对齐,例如条件运算符:

Alignas(_Alignof(int) > 8 ? _Alignof(int) : 8) int a[10];

答案 1 :(得分:1)

定义在32位边界上对齐的char数组的一种可移植的方法是:

union {
    char array[223];
    unsigned long ul;
} u;
如果类型u需要,

unsigned long将在32位边界上对齐,或者可能是2的更大幂,这在您的系统上是非常可能的。该数组以u.array的形式访问。没有编译指示,没有C11特定语法,没有编译器特定扩展。

如果类型uint32_t可用,您可以使用它代替unsigned long

这个解决方案不是真正可移植的,而是解决了不支持_Alignas说明符的过时​​编译器。您的编译器似乎与当前(或以前的)C标准保持同步。

唯一正确的解决方案是使用_Alignas说明符。如果您提供更多上下文,例如您使用的系统和编译器以及为什么需要32位对齐,则可以找到更好的解决方案。