wcslen() возвращает неверный результат при использовании пакета прагмы
Я обнаружил, что wcslen () возвращает неверный результат на gcc (и исправляет на msvc), когда источником является массив wchar_t, член упакованной структуры. Я знаю, что в 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). Кстати, скопированные байты верны (b.buf[7] == '6').
1 ответ
Поведение этого кода не определено и непредсказуемо. Вы проходитеwcslen
function недопустимый указатель, поскольку он не обязательно соответствует требованиям выравнивания для своего типа.
Вероятно, на вашей платформе требование выравнивания для wchar_t
равно 2. Таким образом, указатель, на который вы перешли wcslen
не действует. Вы не видите подобного поведения сstrlen
потому что в этом случае требование выравнивания равно 1, что означает полное отсутствие требования.
Не работайте с упакованными конструкциями, если не знаете, что выполнили требования к выравниванию своей платформы. В противном случае результаты совершенно непредсказуемы. На многих платформах ваш код выйдет из строя.