#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)
Комментариев нет:
Отправить комментарий