#cpp #language_lawyer
Пусть есть структура S следующего вида: struct S { short a; char b; }; И размер sizeof(short) равен 2, а размер sizeof(S) равен 4 (т.е. в структуре есть один padding byte). Вопрос 1. Является ли корректным с точки зрения стандарта языка такой код: S st; st.a = 0; st.b = 0; unsigned char *p = reinterpret_cast(&st); for (size_t i = 0; i != sizeof(st); ++i) unsigned int tmp = p[i]; Вопрос 2. Если код корректен, то гарантируется ли, что в ситуации, когда указатель p указывает на padding byte структуры S, в переменную tmp будет записано некоторое целочисленное значение из отрезка [0; UCHAR_MAX] или допускаются какое-нибудь менее очевидное поведение, например, генерация исключения. Дополнение. Действительно, если есть объект тривиально-копируемого типа T, то составляющие его байты могут быть безопасно скопированы (например, с помощью memcpy) в массив char, unsigned char или std::byte (и обратно). Также можно скопировать некоторый объект тривиально-копируемого типа в другой объект этого же типа (с помощью того же самого memcpy, например.) Однако, в пункте 11.6/12 (n4659) есть занятный пример: unsigned char c; unsigned char d = c; // OK, d has an indeterminate value int e = d; // undefined behavior Не является ли мой пример, в некотором смысле, эквивалентом этого примера из стандарта?
Ответы
Ответ 1
1) Да, каст к char* и unsigned char* разрешен (а каст к другим типам запрещен правилами aliasing) 2) Нет для int. Паддинг можно читать-писать (иначе memcpy сломался бы). Однако, стандарт разрешает читать indeterminate value типа [unsigned] char в присваиваниях где левая стророна это l-value типа [unsigned] char, но запрещает присваивать например int. (При этом неясно, считается ли что паддинг может иметь indeterminate value)
Комментариев нет:
Отправить комментарий