Кто-то обратил мое внимание на следующую программу:
#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
.