如何使用alignas来替换#pragma pack?

18

我正在尝试理解如何使用alignas,想知道它是否可以替代pragma pack。我已经尝试了很多方法来验证它,但没有成功。使用gcc 4.8.1 (http://ideone.com/04mxpI)编译下面的STestAlignas时,始终得到8字节的大小,而使用pragma pack得到的是5字节。我希望STestAlignas的sizeof返回值为5。我在clang 3.3(http://gcc.godbolt.org/)上运行了这段代码,但出现了错误:

!!error: requested alignment is less than minimum alignment of 8 for type 'long' - just below alignas usage.

那么,alignas的最小对齐值是多少呢?

以下是我的测试代码:

#include <iostream>
#include <cstddef>
using namespace std;

#pragma pack(1)
struct STestPragmaPack {
  char c;
  long d;
} datasPP;
#pragma pack()

struct STestAttributPacked {
  char c;
  long d;
} __attribute__((packed)) datasAP;

struct STestAlignas {
  char c;
  alignas(char) long d;
} datasA;

int main() {
    cout << "pragma pack = " << sizeof(datasPP) << endl;
    cout << "attribute packed = " << sizeof(datasAP) << endl;
    cout << "alignas = " << sizeof(datasA) << endl;
}

gcc 4.8.1的结果:

pragma pack = 5
attribute packed = 5
alignas = 8

[2019年8月26日]

看起来在这个主题上有一些标准化的动向。提案p1112 - 支持类布局控制的语言支持 - 建议添加(其中之一)[[layout(smallest)]] 属性,该属性将重新排列类成员,使对齐成本最小化(这是程序员常用的一种技术,但通常会降低类定义的可读性)。但这与 pragma(pack) 的作用不同


我认为 #pragma pack 将永远是一个不可移植的扩展。一些架构不支持未对齐的内存访问。 - R. Martinho Fernandes
3个回答

18

alignas 无法替换 #pragma pack

虽然GCC接受alignas声明,但仍然保持成员正确对齐:满足最严格的对齐要求(在这种情况下,即long的对齐)也满足您指定的要求。

然而,标准明确禁止这种用法,第7.6.2节第5段中有明确规定:

声明中所有的alignment-specifiers 的综合效果不得指定比省略所有alignment-specifiers时声明实体所需的对齐方式更宽松的对齐方式(包括其他声明中的对齐方式)。


3
我想你知道使用未对齐或不正确对齐的数据存在风险和成本。
例如,检索5字节的不正确对齐的数据结构比检索8字节对齐的数据结构更耗时。这是因为,“如果您的5个字节数据不从这4个字节边界之一开始,计算机必须读取内存两次,然后将4个字节组装成一个单一寄存器”(1)。
使用未对齐的数据需要更多的数学运算,并导致ECU消耗更多时间(和功率)。
请注意,C和C ++都被设计为“硬件友好”的语言,这意味着不仅是“最小内存使用”语言,而且主要是专注于效率和快速处理的语言。数据对齐(当不是“我需要存储的内容”时)是一个涉及到另一个概念的概念:“很多时候,软件和硬件类似于生活:为了达到更好的结果,你需要做出牺牲!”
请还考虑是否有错误的假设。例如:“更小/更简单的结构=>更快/更简单的处理”。如果是这种情况,您可能是(完全)错误的。
但是,如果我们假设您的观点是这样的:您根本不关心软件的效率、功耗和快速性,而只是因为硬件限制或理论兴趣而着迷于“最小内存使用”,那么您可能会发现以下阅读有用:
(1)C++中声明、操作和访问未对齐内存 (2)C避免对齐问题 但是,请务必阅读以下内容:
(3)标准对未对齐内存访问有什么规定? 该链接将重定向到此标准的片段:
(4)http://eel.is/c++draft/basic.life#1 (5) 未对齐内存访问:是否定义行为? [这可能是重复的,但可能带有一些额外信息]。

3
谢谢您提供的所有想法,我已经全部了解。但是,您的回答都与我的问题无关。 - marcinj

1

这个新功能是针对过度对齐的数据(用于动态分配),如果我想将我的数据放置在指定的地址对齐(即可被128整除)处,我会使用它。我的问题是如何 - 让我们称之为 - 使数据不对齐,从而通过消除特定结构字段的对齐来使其尽可能小。 - marcinj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接