Кто-то обратил мое внимание на следующую программу:
#include
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 говорится:
Немного -field должен иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned int или каким-либо другим типом, определяемым реализацией.
Так ли это, что поскольку long long int
битовые поля выходят за рамки стандарта, компиляторы могут изобретать свои собственные правила, или можно найти какое-то оправдание поведения Clang и GCC в другом месте в C99?
Я обнаружил это вопрос на StackOverflow, который указывает на направление «компиляторы могут изобретать свои собственные правила», но все же может быть оправдание, которое я пропустил для Clang и GCC, набрав S10.z
как int
.