Объявления массива нулевого размера в структурах были бы полезны, если бы они были разрешены, и если бы семантика была такой, что (1) они вынудили бы выравнивание, но в противном случае не выделяли бы никакого пространства, и (2) индексирование массива будет считаться определеннымповедение в случае, когда результирующий указатель будет в том же блоке памяти, что и структура.Такое поведение никогда не допускалось никаким стандартом C, но некоторые более старые компиляторы позволяли его до того, как стало стандартным для компиляторов разрешать незавершенные объявления массива с пустыми скобками.
Взлом структуры, как обычно реализуется с использованием массива размера 1Хитроумно, и я не думаю, что есть какое-то требование, чтобы компиляторы воздерживались от его взлома.Например, я ожидаю, что если компилятор увидит int a[1]
, он будет в пределах своих прав рассматривать a[i]
как a[0]
.Если кто-то попытается обойти проблемы выравнивания struct hack с помощью чего-то вроде
typedef struct {
uint32_t size;
uint8_t data[4]; // Use four, to avoid having padding throw off the size of the struct
}
, компилятор может стать умным и предположить, что размер массива действительно равен четырем:
; As written
foo = myStruct->data[i];
; As interpreted (assuming little-endian hardware)
foo = ((*(uint32_t*)myStruct->data) >> (i << 3)) & 0xFF;
Такойоптимизация может быть разумной, особенно если myStruct->data
может быть загружен в регистр в той же операции, что и myStruct->size
.Я ничего не знаю в стандарте, который запретил бы такую оптимизацию, хотя, конечно, он нарушил бы любой код, который мог бы получить доступ к вещам, выходящим за пределы четвертого элемента.