【问题标题】:Aligning starting address of array to be multiples of 32 bit?将数组的起始地址对齐为 32 位的倍数?
【发布时间】:2017-07-18 15:03:17
【问题描述】:

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

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

但不工作。

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

【问题讨论】:

  • 32 位是 4 个字节?没有标准的内存分配器将提供至少 4 字节对齐的数据(通常至少 8 字节对齐),因为所提供的内存必须可用于任何目的。还是您的意思是 32 字节?对于 C,请参阅 How to allocate aligned memory only using the standard library? 但是,这主要是关于动态分配的内存;不是全局变量。
  • 我需要数组的起始地址与 32 位对齐(4 的倍数,如 xxxxxx00 或 xxxxxx04 或 xxxxxx08 或 xxxxxx0c 等)。不是字节。这也意味着地址的最后两位为零。
  • @JonathanLeffler:在少于 32 位的平台上,这种情况并不少见。
  • @Olaf:我指的是标准内存分配器,意思是malloc() 等。 char 类型的全局变量可以在任何类型的边界上——在任何类型的机器上。 char 的全局数组不一定在一个偶数边界上对齐,或者更严格地说,在任何平台上,除非用_Alignas(或alignas,如果你包含<stdalign.h>)适当地限定。
  • @Jonathan Leffler 是否可以使用 #pragma 或 attribute 将 char 数组起始地址与 4 字节对齐。

标签: c arrays memory-management global


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 是否适用于C
  • @user3429606:是的,它是 C11。
  • @user3429606:我故意链接到 C 标准(更准确地说是最终草案,但这没有区别)。总体而言,了解该语言是一本不错的读物。
  • @user3429606:如果该答案解决了您的问题,请记住接受/投票(确实如此,除非您使用的编译器已过时 6 年)。
  • @chqrlie:这仅用于结构成员打包,不适用于静态或自动变量的对齐。它也不是可移植的,这是明确要求的。只是不要使用垃圾、过时的编译器。
【解决方案2】:

定义在 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 位对齐,则可以为您的问题找到更好的解决方案。

【讨论】:

  • 我不确定 OP 是询问 32 bit 还是 32 byte 对齐。而且这不是便携式的。
  • @Olaf:OP 明确需要 32 位对齐:为了与 32 位对齐,地址的最后两位应该为 0。提案?
  • "#pragma pack(32)" 将提供 32 个 byte 对齐(在 struct 中)。但是,是的,也许有一个误解。它不可移植,因为语言中的任何类型都没有对齐要求。
  • @Olaf:是的,有一个误解。确实没有对齐要求,但如果他想要一个独立于编译器的解决方案,这已经很接近了。
  • @Olaf:您的解决方案(我会宽恕)不能真正移植到 C11 之前的编译器。 OP 可能正在使用甚至不支持 C99 的 VS2010。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 2012-10-26
  • 2016-12-18
  • 2013-10-11
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多