Тип lvalue.bitfield, когда базовый тип битового поля не является int в C - PullRequest
5 голосов
/ 13 сентября 2011

Кто-то обратил мое внимание на следующую программу:

#include <stdio.h>

struct X50 {
 long long int z:50;
} s50 = { 2 };

struct X10 {
 long long int z:10;
} s10 = { 2 };

int main() {
  printf("%zu %zu %zu\n",sizeof(long long int),sizeof(s10.z+1),sizeof(s50.z+1));
}

Тип выражения sizeof(lv.z+1) вычисляется в соответствии с «обычными арифметическими преобразованиями», которые в значительной степени говорят о том, что размер типа для lvalue lv.z будет отражаться на типе сложения, если это как минимум int.

Я не ожидал, что этот тип будет зависеть от размера битового поля, но это так: и GCC, и Clang печатают 8 4 8 на моем компьютере.

Соответствующими пунктами, которые я нашел в стандарте C99, является пункт 2 в 6.3.1.1, который, похоже, ничего не говорит о битовых полях, не основанных на _Bool, int, signed int или unsigned int. Вторая часть предложения, "Если int может представлять все значения исходного типа, значение преобразуется в int, ...", кажется, применимо только в условиях, описанных в первой части предложение, которое не включает битовые поля на основе long long int.

Кроме того, 6.7.2.1 говорит:

Битовое поле должно иметь тип, который является квалифицированным или неквалифицированным версия _Bool, подписанный int, unsigned int или какой-либо другой определенный реализацией тип.

Это тот случай, когда битовые поля long long int не входят в сферу применения стандарта, компиляторы могут придумывать свои собственные правила или можно найти какое-то оправдание поведению Clang и GCC где-нибудь еще в C99?

Я нашел этот вопрос в StackOverflow, который указывает на направление "компиляторы могут изобретать свои собственные правила", но все же может быть оправдание, которое я пропустил для Clang и GCC, набрав S10.z int.

1 Ответ

3 голосов
/ 14 сентября 2011

6.7.2.1, пункт 10 (выделение добавлено):

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

Таким образом, в ответ на ваш вопрос (который я больше не считаю дубликатом), если компилятор допускает использование типа, определенного реализацией, в качестве типа битового поля, он не обязан выделять достаточно размер для этого типа , размер, достаточный только для реального битового поля. Разумеется, он также может выделить 4 килобайта для битового поля.

...