1

Inspired from this question, I have:

#include<stdio.h> struct st { int a:1; int b:2; }; int main() { struct st obj={1, 2}; printf("a = %d\nb = %d\n",obj.a,obj.b); } 

and I get:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c main.c:10:26: warning: implicit truncation from 'int' to bitfield changes value from 2 to -2 [-Wbitfield-constant-conversion] struct st obj={1, 2}; ^ 1 warning generated. Georgioss-MacBook-Pro:~ gsamaras$ ./a.out a = -1 b = -2 

I think I understand why both bitfields fail to hold their values (as per this answer), but I don't understand why the compiler warns about 2 only, instead of 1 too! Any ideas?

I am using in my Mac:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -v Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 8.1.0 (clang-802.0.38) Target: x86_64-apple-darwin16.3.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin 

In an old Linux system, with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), I got no related warning.

In a Debian installation, with gcc version 4.9.2 (Debian 4.9.2-10) , I got no related warning!

1
  • fyi g++ 5.1.0 produces the 2 warnings as expected. 2 * warning: overflow in implicit constant conversion [-Woverflow] Commented May 10, 2017 at 11:22

2 Answers 2

1

https://en.wikipedia.org/wiki/Two%27s_complement

There could be a couple things that are happening, maybe some experiments can help.

First, it could be that gcc is smart enough to know that a single bit can't really be positive or negative because it's just the single bit.

The other possibility is the order in which gcc evaluates a expression is backwards from what you are thinking. Some compilers evaluate from right to left and in your case, kicked out the error and stopped.

To test, correct the bitfield for b to hold a signed integer for '2' without flipping the sign bit (3 bits should work). If in fixing 'b' you have generated an error for 'a', then you know it's just the compiler evaluation order.

If fixing 'b' doesn't cause 'a' to kick out a warning, then gcc is performing some internal optimization on a single bit field.

Also, changing your bitfield types to 'uint' should also fix the warnings, in which case it is simply the sign bit of the representation getting flipped.

Happy coding.

EDIT Relevant source code: https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaChecking.cpp#L8812

Sign up to request clarification or add additional context in comments.

3 Comments

When I fix b, I get no warning at all for a . . .But +1 for the idea!
Cool. I would probably put money on gcc having a specialization for a single bit case. In C++ this is done using partial template specialization, and I think gcc is written in C++.
I found the source code check for clang here: github.com/llvm-mirror/clang/blob/master/lib/Sema/…
0

int b:2; is 2 bit width signed integer. Number 2 (unsigned) is represented as 10 in binary and because source int is signed, you actually get signed number saved to memory.

This is the reason you got this warning.

Values you can save to 2-bit signed int are: (-2 = 11, -1 = 10, 0 = 00, 1 = 01)

Reason why you did not get in both cases is that int a:1 is only 1 bit and can hold numbers 1 or 0, without negative numbers.

2 Comments

Thanks for the answer but the question is why I didn't get both warnings! :)
But if this is the case, I would expect 1 to be printed. See, the initial linked question for more please.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.