I've found that wcslen() returns incorrect result on gcc(and correct on msvc) when source is wchar_t array, member of packed struct. I know on linux sizeof(wchar_t) == 4 and on windows its 2 but still can't understand how packing affects wcslen() function. If I change wchar_t/wcslen to char/strlen it works as expected.
#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);
}
Why this code compiled with gcc returns 7? It should return 8(as msvc does). Btw copied bytes are correct(b.buf[7] == '6').
The behavior of this code is undefined and unpredictable. You're passing the
wcslen
function an invalid pointer since it doesn't necessarily meet the alignment requirements for its type.Likely on your platform, the alignment requirement for
wchar_t
is 2. So the pointer you've passed towcslen
is not valid. You don't see similar behavior withstrlen
because the alignment requirement is 1 in that case, which means no requirement at all.Don't operate on packed structures unless you know that you've complied with your platform's alignment requirements. Otherwise, the results are entirely unpredictable. On many platforms, your code will crash.