Безопасно ли утверждать (sizeof (A) == sizeof (B)), когда A и B "одинаковы"?

Предположим, у меня есть два класса, которые я ожидаю, чтобы иметь точно такую же структуру памяти:

struct A {
    int x;
    int y;
};

/* possibly more code */

struct B {
    int a;
    int b;
};

Есть ли что-то в стандарте, что гарантирует, что я могу безопасно static_assert(sizeof(A) == sizeof(B))?

В качестве более слабого варианта рассмотрим

struct C {
    int a;
};

static_assert( sizeof(A) >= sizeof(C) );   // can this ever fail?
static_assert( sizeof(A) >  sizeof(C) );   // can this ever fail?

Этот вопрос был вызван этим. Наивно я не ожидал бы, что какое-либо из утверждений потерпит неудачу, но гарантировано ли это?

Ответ 1

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

Все эти вещи попадают в категорию вещей, которые Стандарт мог бы сделать для соответствующей реализации, но от качественных реализаций, как правило, следует воздерживаться, даже если это разрешено Стандартом. Стандарт не прилагает усилий, чтобы запретить реализациям делать глупости, а также не догадываться, могут ли какие-то специализированные реализации иметь веские причины для обработки чего-либо нетипичным образом. Вместо этого он ожидает, что разработчики компиляторов попытаются удовлетворить потребности своих клиентов, независимо от того, требует ли это Стандарт или нет.

Ответ 2

Придуманный контрпример:

#include <stdint.h>

struct A {
    int32_t a;
    int64_t b;
};

#pragma pack(4)

struct B {
    int32_t a;
    int64_t b;
};

static_assert(sizeof(A) == sizeof(B));

Компиляция с g++ в 64-битном Linux дает:

a.cc:15:1: error: static assertion failed
static_assert(sizeof(A) == sizeof(B));

Ответ 3

Единственный случай, когда ваше утверждение может быть ложным, - это когда существует разница в критериях упаковки. В противном случае утверждение должно быть верным.

Компилятор имеет только определение структуры для определения смещения элемента, поэтому, если вы не будете использовать непротиворечивую структуру, вы не сможете получить доступ к структуре.