使用编译指示包时,wcslen()返回错误结果

时间:2019-10-22 18:18:48

标签: c++ gcc visual-c++ wchar-t pragma-pack

我发现当源是打包结构的成员wchar_t数组时,wcslen()在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编译的代码返回7?它应该返回8(就像msvc一样)。 Btw复制的字节是正确的(b.buf [7] =='6')。

1 个答案:

答案 0 :(得分:4)

此代码的行为是不确定的和不可预测的。您正在向wcslen函数传递一个无效的指针,因为它不一定满足其类型的对齐要求。

就像在您的平台上一样,wchar_t的对齐要求为2。因此,您传递给wcslen的指针无效。您不会看到strlen的类似行为,因为在这种情况下对齐要求为1,这意味着完全没有要求。

除非您知道已遵守平台的对齐要求,否则请不要在打包结构上运行。否则,结果将完全不可预测。在许多平台上,您的代码将崩溃。