gpt4 book ai didi

c - 长对齐问题(MSVC vs. GCC)

转载 作者:太空宇宙 更新时间:2023-11-04 00:27:54 24 4
gpt4 key购买 nike

我正在编写 C 跨平台库,但最终我的单元测试出现错误,但仅限于 Windows 机器。我跟踪了这​​个问题,发现它与结构对齐有关(我使用结构数组来保存多个相似对象的数据)。问题是:memset(sizeof(struct)) 和设置结构成员一一产生不同的字节到字节结果,因此 memcmp() 返回“不等于”结果。

这里是演示代码:

#include <stdio.h>
#include <string.h>

typedef struct {
long long a;
int b;
} S1;

typedef struct {
long a;
int b;
} S2;

S1 s1, s2;

int main()
{
printf("%d %d\n", sizeof(S1), sizeof(S2));

memset(&s1, 0xFF, sizeof(S1));
memset(&s2, 0x00, sizeof(S1));

s1.a = 0LL; s1.b = 0;

if (0 == memcmp(&s1, &s2, sizeof(S1)))
printf("Equal\n");
else
printf("Not equal\n");

return 0;
}

此代码与 MSVC 2003 @ Windows 产生以下输出:

16 8
Not equal

但是与 GCC 3.3.6 @ Linux 相同的代码按预期工作:

12 8
Equal

这让我的单元测试变得非常困难。

我是否正确理解 MSVC 使用最大 native 类型的大小(long long)来确定与结构的对齐?

有人可以给我建议,我该如何更改我的代码以使其更健壮地解决这个奇怪的对齐问题?在我的真实代码中,我通过通用指针处理结构数组以执行 memset/memcmp,我通常不知道确切的类型,我只有 sizeof(struct) 值。

最佳答案

您的单元测试的预期是错误的。它(或它测试的代码)不应逐字节扫描结构的缓冲区。对于字节精确数据,代码应该在堆栈或堆上显式创建一个字节缓冲区,并用每个成员的提取物填充它。通过对整数值使用右移操作并将结果转换为字节类型(例如(unsigned char)),可以以独立于 CPU 字节序的方式获得提取物。

顺便说一句,您的代码段写了过去的 s2。你可以通过改变这个来解决这个问题

memset(&s2, 0x00, sizeof(S1));

s1.a = 0LL; s1.b = 0;

if (0 == memcmp(&s1, &s2, sizeof(S1)))

对此,

memset(&s2, 0x00, sizeof(S2));

s1.a = 0LL; s1.b = 0;

if (0 == memcmp(&s1, &s2, sizeof(S2)))

但结果在技术上是“未定义的”,因为结构中成员的对齐是特定于编译器的。

关于c - 长对齐问题(MSVC vs. GCC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/611123/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com