问题标签 [struct-member-alignment]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
1309 浏览

c - 结构体成员对齐——使用 16 位和 32 位编译器的不同 sizeof

我有一个用于向控制板构造消息的结构,我需要保持 C167 16 位 Keil 编译器和 32 位 Tricore gcc 编译器之间的软件兼容性。

该数组new_weld_status[2]在 16 位编译器上占用 2 个字节,但在 32 位编译器上占用 4 个字节。new_weld_status[2]在用 gcc 编译时,我正在考虑用 union 替换所有的。但是是否有一个我可以用于 gcc 的开关,使字符适合/对齐 2 个字节?

谢谢

0 投票
0 回答
56 浏览

c++ - 是否有保证的方法可以避免基类和派生类之间的填充?

我正在开发一个网络程序,该程序将处理具有标头部分和有效负载部分的数据包。标头是可变长度的,根据网络条件添加或删除扩展段。用户数据部分是一个普通字节缓冲区,尽管在数据包构建或使用期间它可能被视为某种结构或其他结构。

我希望有一个基类来构建和操作标头,如果需要插入扩展字段,标头字节(可能)向前或向后移动,以及包含用户数据的派生类。例如:

是否有一种标准方法可以保证hdrandpayload1或之间没有填充payload2,以便我可以传递start()write()让标头和连续有效​​负载传输到网络?例如,如果(sizeof(hdr) % BIG_STANDARD_ALIGNMENT) == 0)then 派生类hdr将在没有任何额外填充的情况下启动?

另一种方法是使用分散/收集 I/O,但这似乎是一个复杂的设置,我不确定将数据包片段收集在一起以在单个 UDP 数据包中传输是否有效。

0 投票
2 回答
643 浏览

c++ - 使用 std::bitset 的联合成员进行结构填充

在我解决了这个问题的问题后,我继续扩展我的代码的这个版本,以将我以前的模板版本中的数据字段的联合与这个版本合并,到目前为止我有这个:

主文件

寄存器.h

注册.cpp

输出

在查看bitset类型大小的打印输出数据后,将它们与它们作为联合中结构成员的实际大小进行比较。我试图弄清楚这里发生了什么。

我不确定我是否正确执行 sizeof 计算是否与内部存储bitset有关类型是std::bitset类型的。从标题中您可以看到这些有 4 种变体:bitset<8> = Byte, bitset<16> = Word, bitset<32> = DWord&bitset<64> = QWord

本质上应该有这些的可分割映射:

因此,当我尝试在联合中使用它们时:

我认为通过使用我在此联合上方显示的模式,我可以将数据打包成字节大小对齐:

然而,这似乎并没有像我预期的那样发生。

我的总体目标是模拟上面我表达的模式,以便寄存器的基本大小为 64 位或 8 字节宽,并且通过使用联合,我将能够从完整的 qword 访问子字节、字或双字.

您能否详细说明我在这里缺少的内容?我不确定它是否与如何std::bitset存储在内存中有关,是否与结构对齐有关,或者是否与联合本身有关。

0 投票
7 回答
6469 浏览

c++ - 如何组织结构中的成员以在对齐上浪费最少的空间?

[不是结构填充和包装的副本。这个问题是关于填充的发生方式和时间。这个是关于如何处理的。]

我刚刚意识到由于 C++ 中的对齐而浪费了多少内存。考虑以下简单示例:

使用 g++ 时,程序给出以下输出:

那是 50% 的内存开销!在 134'217'728 Xs 的 3 GB 数组中,1 GB 将是纯填充。

幸运的是,问题的解决方案非常简单——我们只需要double b左右交换int c

现在结果更令人满意:

但是有一个问题:这不是交叉兼容的。是的,在 g++ 下,anint是 4 个字节,adouble是 8 个字节,但这不一定总是正确的(它们的对齐方式也不必相同),所以在不同的环境下,这个“修复”不仅没用,而且通过增加所需的填充量,它还可能使事情变得更糟。

是否有可靠的跨平台方法来解决这个问题(最小化所需的填充量,而不会因未对齐而导致性能下降)?为什么编译器不执行这样的优化(交换结构/类成员以减少填充)?

澄清

由于误解和困惑,我想强调我不想“打包”我的struct. 也就是说,我不希望它的成员不对齐,从而降低访问速度。相反,我仍然希望所有成员都是自对齐的,但是以一种在填充上使用最少内存的方式。这可以通过使用例如此处和Eric Raymond的 The Lost Art of Packing中描述的手动重新排列来解决。我正在寻找一种自动化且尽可能跨平台的方法来执行此操作,类似于提案 P1112中针对即将推出的 C++20 标准所描述的方法。

0 投票
0 回答
55 浏览

arrays - 对齐结构的阵列,可诱导单个成员的规则阵列

如果我有一个结构(例如employee下面),只有当结构的大小是所有成员大小的(最小)公倍数(LCM)时,这种结构的数组才会引发结构的所有成员的跨步数组。

否则,将有指向数组中特定成员实例的指针,它们没有整数指针距离(以成员类的大小衡量)。

因此,例如,给定这个结构:

A std::vector<employee> v(或employee[N]就此而言的数组)诱导成员的跨步数组salary(使用 stride sizeof(employee)/sizeof(short))以及 的跨步数组age

也就是说,工资数组是由 随机访问的&(v.data()->salary) + sizeof(employee)/sizeof(short)* n

但是,它不会引起名称的跨步数组,因为sizeof(employee)(=48) 不是sizeof(std::string)(32) 的倍数(在我的系统中)。

当然,我可以以其他方式定义结构以允许这样做:

我想知道找到这个正确的alignas论点是否是实现这一目标的唯一方法。此外,如果有一种自动获取该数字的方法,而无需手动查找公倍数。

我似乎没有反思的最一般的方法是做这样的事情:

也就是说,我必须提前枚举所有成员。我可以constexpr std::lcm通过链接它多次使用)。

这是正确的方法吗?

此外,人们总是可以找到这种甚至不起作用的病态情况,因为存在额外的限制,即对齐需要是 2 的幂(在某些系统中)。在这种情况下,公倍数也需要是 2 的幂,并且可以是一个巨大的数字:

...error: requested alignment ‘3296’ is not a positive power of 2

为了使对齐 LCM 起作用,我必须手动更改特定成员的对齐方式或将constexpr上限添加到最接近的 2 次幂。

但是,这仍然不能解决问题,因为alignas它不是 的一部分password_type,似乎唯一的解决方案是拥有一个std::array也需要内部对齐参数的版本!std::aligned_array<char, 103, 128>.

好的,我仍然可以这样做,但代价是修改employee最初未耦合的其他类。

它可能最终会起作用。但这需要大量的手动工作,并且可能会在我更改系统或添加新成员等时更改。

有没有更自动的方法来做到这一点?或遵循一些约定以使这个问题不那么痛苦

0 投票
2 回答
162 浏览

c - 在 C 中的位域结构中添加的额外位

我正在尝试为 CAPWAP 协议创建客户端 C 代码。我尝试使用位字段结构实现 CAPWAP 标头。但是在使用 sendto() 通过套接字发送这个结构之后,当我使用wireshark 嗅探数据包时,我发现在它们之间添加了一些额外的位。我不知道这是从哪里来的。请求帮助。提前致谢。

线鲨

我尝试评论结构的最后几个成员以使其 4 字节对齐。问题仍然存在。

这是原始标题

我试着评论这些

这是填充结构的地方

这是前 32 位的wireshark 的输出

预期结果:位应按结构中提到的顺序错误:在结构成员之间添加额外位

0 投票
1 回答
66 浏览

c++ - vcpkg:指定结构成员对齐

我有一些旧代码是用 1 字节(参数/Zp1结构成员对齐打包编译的,我正在向它们添加带有 gTest 的单元测试。我vcpkg用来安装 gTest,但它是使用 8 字节打包的默认设置编译的。我在使用 VS2019 的 Windows 上。

是否可以指定使用哪个包装(参数/Zpvcpkg

0 投票
1 回答
524 浏览

visual-studio-2012 - 如何在 CMake 中为 Struct Member Alignment 设置 Visual C 构建选项?

我想知道如何在我的 CMakeLists.txt 中设置以下 Visual Studio 构建选项。

Struct Member Alignment = 1 Byte (/Zp1),在项目属性(配置属性 -> C/C++ -> 代码生成)中设置。

0 投票
1 回答
145 浏览

c++ - 从外部 API 比较两个相同类型的结构

所以基本上我正在尝试比较VkPhysicalDeviceFeaturesVulkan 的两个,一个来自VkPhysicalDevice我正在查看的,另一个对应于我实际需要的一组功能。VkPhysicalDeviceFeatures结构包含VkBool32成员(它们是 的 typedef )uint32_t,但 vulkan 的每个次要版本都可以添加未知数量的这些功能。我想做的只是将每个结构的成员相互比较,而不是为了相等,更多的是逻辑比较。如果物理设备结构中的相应成员为假,但我的结构对该成员具有真,那么比较应该返回假。

我能想到的唯一方法就是这个答案发布的内容:

这就是我想要的(尽管有一种方法可以通过名称查看哪个特定成员未能通过比较,但我想如果没有反射这是不可能的)但我认为 C++ 不能保证像这样的严格对齐?我有没有跨平台的方式来完成这个?

0 投票
0 回答
64 浏览

c++11 - 对齐一个简单的类以允许在没有 UB 的情况下访问数组

假设我有以下简单的类:

由于我希望对员工数组中的员工成员进行类似数组的访问name,因此我需要例如偏移量是可分割的:

为了确保我使用的是alignas指令:

这似乎可以完成这项工作(现在static_assert上述通过了)。

但是,当我打开clangUB(未定义的行为清理程序)并尝试构建该对齐版本的类 clang 的数组时,检测到错误:

那么让alignment员工和name成员兼容的正确方法是什么?(所以数组的成员可以通过指针std::string*算术访问)

奖励问题:如何对齐所有成员以允许对employees 数组的所有成员进行数组访问。

有关更多详细信息,请参见此处:对齐/偏移结构的特定成员

基本上,我注意到根据 clang 有效的解决方案是 UB,我正在寻找替代方案。


通过成员的数组访问,我的意思是能够做到这一点:


请注意,我发现这很有效(在我的系统中),工作是否匹配步幅,而 clang 并没有说是 UB:

这是迄今为止我发现的唯一不产生 UB 的选项。我想知道是否还有更好的方法。

最惯用的路径似乎使用alignas但它也根据clang触发UB。