wcslen() returns 使用 pragma pack 时结果不正确
wcslen() returns incorrect result when pragma pack used
我发现当源是 wchar_t 数组时,wcslen() return 在 gcc 上的结果不正确(在 msvc 上更正),打包结构的成员。我知道 linux sizeof(wchar_t) == 4 和 windows 它的 2 但仍然无法理解打包如何影响 wcslen() 函数。如果我将 wchar_t/wcslen 更改为 char/strlen,它会按预期工作。
#include <cstdint>
#include <cwchar>
#include <cstring>
#pragma pack(push, 1)
struct A
{
uint8_t c;
};
struct B
{
A a;
wchar_t buf[9];
};
#pragma pack(pop)
int main()
{
const wchar_t* s = L"05.00.06";
B b{};
memcpy(b.buf, s, wcslen(s) * sizeof(wchar_t));
return wcslen(b.buf);
}
为什么这段代码是用 gcc returns 7 编译的?它应该 return 8(就像 msvc 那样)。顺便说一句,复制的字节是正确的(b.buf[7] == '6')。
此代码的行为未定义且不可预测。您向 wcslen
函数传递了一个无效指针,因为它不一定满足其类型的对齐要求。
可能在您的平台上,wchar_t
的对齐要求是 2。因此您传递给 wcslen
的指针无效。您看不到 strlen
的类似行为,因为在这种情况下对齐要求为 1,这意味着根本没有要求。
除非您知道您已符合平台的对齐要求,否则不要对压缩结构进行操作。否则,结果完全不可预测。在许多平台上,您的代码会崩溃。
我发现当源是 wchar_t 数组时,wcslen() return 在 gcc 上的结果不正确(在 msvc 上更正),打包结构的成员。我知道 linux sizeof(wchar_t) == 4 和 windows 它的 2 但仍然无法理解打包如何影响 wcslen() 函数。如果我将 wchar_t/wcslen 更改为 char/strlen,它会按预期工作。
#include <cstdint>
#include <cwchar>
#include <cstring>
#pragma pack(push, 1)
struct A
{
uint8_t c;
};
struct B
{
A a;
wchar_t buf[9];
};
#pragma pack(pop)
int main()
{
const wchar_t* s = L"05.00.06";
B b{};
memcpy(b.buf, s, wcslen(s) * sizeof(wchar_t));
return wcslen(b.buf);
}
为什么这段代码是用 gcc returns 7 编译的?它应该 return 8(就像 msvc 那样)。顺便说一句,复制的字节是正确的(b.buf[7] == '6')。
此代码的行为未定义且不可预测。您向 wcslen
函数传递了一个无效指针,因为它不一定满足其类型的对齐要求。
可能在您的平台上,wchar_t
的对齐要求是 2。因此您传递给 wcslen
的指针无效。您看不到 strlen
的类似行为,因为在这种情况下对齐要求为 1,这意味着根本没有要求。
除非您知道您已符合平台的对齐要求,否则不要对压缩结构进行操作。否则,结果完全不可预测。在许多平台上,您的代码会崩溃。