Нет, это не гарантированно работает.
Прежде всего, нет гарантии на размещение в памяти не связанных между собой объектов. Единственный раз, когда объекты гарантированно размещаются в памяти непрерывно, это
- если вы поместите их рядом друг с другом (например, вы вручную выделите некоторое количество байтов и разместите их один за другим) или
- если они находятся в массиве (элементы массива всегда смежные
Итак, действует следующее:
int ints[2];
*(&ints[0] + 1) = 42;
Код в вопросе недействителен, потому что объекты foo
и bar
совершенно не связаны и могут быть размещены в любом месте памяти.
Существует несколько связанная с этим проблема, заключающаяся в том, что в структуре могут присутствовать и безымянные байты заполнения.
- между членами структуры (чтобы элементы были правильно выровнены) и
- в конце структуры (чтобы объекты этого типа структуры могли быть размещены непрерывно в массиве)
Это означает, что следующее недопустимо, потому что в конце Foo
может быть безымянный отступ:
Foo foos[2];
*(&foos[0].a + 1) = 42;
Как правило, вы никогда не должны полагаться на размещение двух объектов относительно друг друга, если они не находятся в массиве. Не имеет значения, объявляются ли объекты в исходном коде рядом друг с другом, имеют ли они одинаковый тип или имеют одинаковый размер: просто нет гарантии.