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

Aligning starting address of array to be multiples of 32 bit?

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

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

但不工作。

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

包装是完全无关的东西。要对齐静态变量或结构成员(相对于结构开始),请使用标准 _Alignas specifier.

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

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

(如果除法有余数就会出问题;你的意思是32bits还是32bytes?A标准不保证字节有 8 位。)

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

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

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

union {
    char array[223];
    unsigned long ul;
} u;

u 将在 32 位边界上对齐,或者如果类型 unsigned long 需要,则可能是 2 的更大幂,这在您的系统上很有可能。该数组被访问为 u.array。没有编译指示,没有特定于 C11 的语法,没有特定于编译器的扩展。

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

此解决方案并不是真正可移植的,而是一种针对不支持 _Alignas 说明符的过时​​编译器的变通方法。您的编译器似乎不符合当前(或以前的)C 标准。

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