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



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

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

但不起作用。

PS:为了与32位对齐,地址的最后两位应为0。

打包是完全无关紧要的。若要对齐静态变量或结构成员(相对于结构开始(,请使用标准_Alignas说明符。

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

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

(如果除法有余数,这将导致问题;你的意思是 32还是 32字节?标准不保证一个字节有 8 位。

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

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

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

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

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

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

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

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

最新更新