Можно ли модифицировать padding байты?

Рейтинг: 3Ответов: 2Опубликовано: 11.06.2023

Например:

struct A {
  char x;
  int y;
} a{1, 2}, b = a;

int main() {
  reinterpret_cast<unsigned char*>(&a)[1] = 2;
}

Легально ли это? И останется ли b равным a?

Ответы

▲ 2

Компиляторы не обязаны выполнять никакие осмысленные действия, если вы выполняете код с "неопределённым" эффектом. Они даже могут выполнить разные действия при разных опциях компиляции.

Compilers are not required to diagnose undefined behavior (although many simple situations are diagnosed), and the compiled program is not required to do anything meaningful.

Компиляторы не обязаны диагностировать неопределенное поведение (хотя диагностируются многие простые ситуации), и от скомпилированной программы не требуется делать что-либо значимое.

Undefined behavior

По-поводу заполняющих байтов, компилятор может сам их использовать по своему усмотрению. Например размерами массива или кодом класса с виртуальными функциями.

▲ 0

Сначала немного определений.

Для объекта типа T существуют "представление объекта" (object representation), которое является последовательностью из N unsigned char объектов, где N == sizeof(T), и "представление значения" (value representation) - множество бит, которое участвует в представлении значения типа T. Биты в представлении объекта, которые не являются частью представления значения, называются "заполняющими битами" (padding bits).

Для тривиально копируемых типов "представление значения" - это набор битов из представления объекта, определяющих значение, которое является одним дискретным элементом из набора значений, определяемых реализацией (implementation-defined). Это делает модель памяти C++ совместимой с языком C.

Т.о. если модификация объекта затрагивает исключительно заполняющие биты и не затрагивает биты представления значения, то именованые члены-данные x и y сохранят свои значения. Говорить о том, будет ли a == b истиной можно лишь в том случае, если для struct A определён operator==. В текущем случае он не определён, но если сравнивать почленно, то их можно рассматривать как равные.