This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Manipulating bit fields is behaving inconsistently


On Thu, Feb 18, 2016 at 5:31 PM, Wink Saville <wink@saville.com> wrote:
> You've convinced me that this isn't a bug, but I assume you'd agree
> its weird at best. I tested it with clang and it works as I'd expect:
>
> $ make
> clang -x c -m64 -O3 -Wall -o test.o -c test.c
> objdump -d test.o > test.txt
> clang -m64 -O3 -Wall test.o -o test
> wink@wink-desktop:~/prgs/large_fields_are_odd
> $ ./test
> x.f0=0xfff
>   g0=0x1ffe expect 0x1ffe
> x.f1=0xfffffffffffff
>   g1=0x1ffffffffffffe expect 0x1ffffffffffffe
>
> Here is the make file:
>
> CC = clang
> CFLAGS = -m64 -O3 -Wall
>
> all: test
>
> test.o: test.c
> $(CC) -x c $(CFLAGS) -o test.o -c test.c
> objdump -d test.o > test.txt
>
> test: test.o
> $(CC) $(CFLAGS) test.o -o test
>
> clean:
> rm -f test test.o test.txt
>
>
> Do you think gcc should change?


No, clang should.  GCC behaved this way since forever.

> On Thu, Feb 18, 2016 at 2:52 AM, Bernd Edlinger
> <bernd.edlinger@hotmail.de> wrote:
>> Hi,
>>
>>> struct fields {
>>>   long long unsigned f0:12;
>>>   long long unsigned f1:52;
>>> } __attribute__((__packed__));
>>
>> the C99 standard ISO/IEC 9899 forbids this type:
>>
>> 6.7.2.1 Structure and union specifiers
>>
>> 4 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.
>>
>> The C standard simply does not promote the bit-field value to any type larger than int or
>> unsigned int.
>>
>> GCC chooses to do the larger than int computations in an artificial 52-bit type, but it is a
>> non-standard extension.
>>
>> And if you compile your example with -Wall you'll see the problem:
>>
>> gcc -m32 -O3 -Wall  test.c
>> test.c: In function 'main':
>> test.c:17:21: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 2 has type 'int' [-Wformat=]
>>    printf("x.f0=0x%llx\n", x.f0);
>>                      ^
>> test.c:19:21: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 2 has type 'long long unsigned int:52' [-Wformat=]
>>    printf("x.f1=0x%llx\n", x.f1);
>>                      ^
>>
>> so especially the first warning is no joke:
>>
>> ./a.out
>> x.f0=0x80497b400000fff
>>   g0=0x1ffe expect 0x1ffe
>> x.f1=0xfffffffffffff
>>   g1=0xffffffffffffe expect 0x1ffffffffffffe
>>
>>
>> OTOH that is perfectly OK for C++:
>>
>> gcc -x c++ -m32 -O3 -Wall  test.c
>>
>> ./a.out
>> x.f0=0xfff
>>   g0=0x1ffe expect 0x1ffe
>> x.f1=0xfffffffffffff
>>   g1=0x1ffffffffffffe expect 0x1ffffffffffffe
>>
>>
>> Regards
>> Bernd.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]