5

Someone drew my attention to the following program:

#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));
}

The type of expression sizeof(lv.z+1) is computed according to the "usual arithmetic conversions", that pretty much say that the size of the type for the lvalue lv.z will be reflected on the type of the addition, as long as it is at least int.

I did not expect this type to depend on the size of the bitfield, but it does: both GCC and Clang print 8 4 8 on my computer.

The relevant clauses that I found in the C99 standard are clause 2 in 6.3.1.1, that does not seem so say anything about bitfields not based on _Bool, int, signed int, or unsigned int. The second part of the clause, "If an int can represent all values of the original type, the value is converted to an int, ...", only seems to apply in the conditions described in the first part of the clause, that do not include bitfields based on long long int.

Besides, 6.7.2.1 says:

A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

Is it the case that since long long int bitfields are outside the scope of the standard, compilers can invent their own rules, or can some kind of justification for Clang and GCC's behaviors be found elsewhere in C99?

I found this question on StackOverflow, which points in the "compilers can invent their own rules" direction, but there could still be a justification that I missed for Clang and GCC both typing S10.z as int.

Community
  • 1
  • 1
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 1
    What part of the other question saying "this isn't specified in the standard" wasn't a satisfactory answer for you? The standard doesn't say a whole lot about bitfields - what you've quoted is basically it - and if it says something is "implementation-defined," it usually doesn't go on to talk about it in great detail. – Chris Lutz Sep 13 '11 at 20:04
  • @Chris Lutz I am emphatic that the answers to the question you link do not tell whether GCC and Clang's behavior is the result of a constraint imposed by the standard, which is not the same question as whether `long long int` bitfields are a language extension (they are). – Pascal Cuoq Sep 13 '11 at 20:07
  • @Chris Lutz Why it matters: I work on a static analyzer, that I don't wish to be good only for GCC and Clang programs (although these are the compilers I use everyday). If any C99 compiler that implements long long bitfields has to do it the same way as GCC, I'll just implement these same rules too. If it can be done differently, I have to either reject that extension, or forever worry that another compiler types `X10.z` as `long long` and my analyzer predicts the wrong thing about programs compiled with that compiler. – Pascal Cuoq Sep 13 '11 at 20:16
  • After checking the standard, I agree. I wish SO had a better close/reopen system that allowed me to retract my close votes. As it is, I've posted an answer with a part of the standard I think is relevant. – Chris Lutz Sep 13 '11 at 20:16

1 Answers1

3

6.7.2.1 paragraph 10 (emphasis added):

An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

So in answer to your question (which I no longer think is a duplicate), if a compiler allows an implementation-defined type to be used as the type of a bitfield, it doesn't appear to be required to allocate enough size for that type, only enough size for the actual bitfield. Of course, it also appears to be within its rights to allocate 4 kilobytes for the bitfield.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • Considering that the bitfield's "natural" type is that of the addressable storage unit it is stored in when it comes out of memory, and that C99's usual arithmetic conversions philosophy only require it to be promoted up to `int` to be operated on, GCC's behavior seems more normal after reading your answer. But I must still worry about other compilers doing it differently. – Pascal Cuoq Sep 13 '11 at 21:29
  • They might well do it differently. Based on the standard, the compiler is only required to allocate enough space for the bitfield. So it looks like all you can guarantee is `sizeof(s10.z1 + 1) >= sizeof(int)`? – Chris Lutz Sep 13 '11 at 22:44