Keith Devens .com |
Tuesday, December 2, 2008 | ![]() |
| Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.... – Ferris Bueller | ||
|
| ← The Small language | William Safire: After Arafat, Hope → |

Adam Langley (http://www.imperialviolet.org) wrote:
Keith (http://keithdevens.com/) wrote:
You win! 
I've never used the :1 before. I was thinking it was something along those lines, but didn't get to look it up before I went to bed.
Interestingly, while my copy of GCC gave the correct answer, my friend tried it on a less frequently used compiler and it said 1.
Keith Gaughan (http://talideon.com/) wrote:
1 or -1 depending on whether the compiler uses signed or unsigned ints.
Keith (http://keithdevens.com/) wrote:
I thought ints were always supposed to be signed in C unless you ask for unsigned?
Aggelos (http://users.uoi.gr/agorf/) wrote:
Since there are many versions of C, this might not be the case in all of them. As far as I know -in ANSI C- every integer is signed by default and that's why the "unsigned" operator is for. BTW, I didn't know about the ":" operator in structs either.
Keith Gaughan (http://talideon.com/) wrote:
I'm pretty sure that ISO standard states that they may be signed or unsigned (hence the "signed" and "unsigned" keywords).
I don't have my copy of K&R here with me at work, so I can't check, but my copy of Writing Solid Code--good book: you should get a copy if you don't already have it along with Software Exorcism--says that ISO C says that they can be signed or unsigned.
Keith (http://keithdevens.com/) wrote:
I whipped out my copy of K&R (2nd ed. updated for ANSI C), and it says that whether CHARs are signed or not is machine-dependent, and it seems to indicate that all other integral types are signed by default. Pg 211:
The signed specifier is useful for forcing char objects to carry a sign; it is permissible but redundant on other integral types.
Ah, here we go, pg 196:
The int types all represent signed values unless specified otherwise.
Their size, of course, is machine dependent, but their signed-ness is specified.
Keith Gaughan (http://talideon.com/) wrote:
I blame Microsoft! 
You're right though. I checked K&R myself when I got home to see if what Writing Solid Code said was correct (in the standard as opposed to practice), and said just what you did.
Aggelos (http://users.uoi.gr/agorf/) wrote:
As I was reading the K&R2 (I want to finish it), I reached the paragraph that talks about bit fields in structs. I remembered this code so I got back to see if I can understand it.
AGL said:
The :1 in the struct sets the bit length of the field. Then you set it to 1, but it's a signed type, right? So all bits set true (where all = one of them) == -1.
Why is that? Yes i is a signed int, but it could also be 1 right? Since 1 can be either signed or unsigned int. So, why -1?
Keith (http://keithdevens.com/) wrote:
Why is that? Yes i is a signed int, but it could also be 1 right? Since 1 can be either signed or unsigned int. So, why -1?
It can't be 1. A 1 bit signed integer must be -1. The leftmost bit of a signed integer always represents the sign, and regardless of the field length all 1's represents -1. So, if you have a 1 bit signed value you get -1. Make sense? (If not, brush up on your two's complement.)
Aggelos (http://users.uoi.gr/agorf/) wrote:
I know about the signs (0 representing positive, and 1 negative) as well as the two's complement. What I don't get is why
A 1 bit signed integer must be -1.
Why 'must'? Both -1 and 1 can be signed integer values, so why -1? Maybe I should show how I walk through the code.
b.a = 1;
b.a is just a bit. 1 is a signed integer (00000000 00000000 00000000 00000001 on 32-bit machines). To be honest I don't know what happens here. I suppose b.a takes the value of the rightmost bit of 1 decimal, which is 1.
i = b.a;
i is a signed integer and b.a is just a bit (with value 1). So how is this conversion done? How do you convert a single bit into a signed integer?
My point: You just have one single bit, with value 1. And it is signed. How do you know if it is a '-' or a '1'?
Keith (http://keithdevens.com/) wrote:
Keep in mind that when a signed value is converted to a longer signed value it's sign extended. So, 1 (or 11111111) becomes 11111111 11111111 11111111 11111111 when converted to a 32 bit signed integer (and "all ones" in a signed variable is always -1).
If you're converting between signed and unsigned, things get more complicated. K&R has this example on pg 44:
... suppose that int is 16 bits long and long is 32 bits. Then -1L < 1U because 1U, which is an int, is promoted to a signed long. But -1L > 1UL, because -1L is promoted to unsigned long and thus appears to be a large positive number.
Aggelos (http://users.uoi.gr/agorf/) wrote:
So in this:
i = b.a;
b.a which is one bit of value 1 and becomes (in binary): 11111111 11111111 11111111 11111111; it is sign exteneded. But since you have one bit, is this single bit the sign? And if yes, where is your number then? Still, I have the same question. Why should 1 be - and not just positive 1 that gets extended to 00000000 00000000 00000000 00000001?
Aggelos (http://users.uoi.gr/agorf/) wrote:
OK, I think I got it now (with a help of a friend).
In
b.a = 1;
1 is 00000000 00000000 00000000 00000001. The 0s are trimmed so all you got in the memory is one bit of value 1.
In
i = b.a;
Your one bit of value 1 has to be converted to 32-bit integer. So it is padded with 1s and becomes 11111111 11111111 11111111 11111111, which in hex is FFFFFFFF which with printf("%x", 0xFFFFFFFF); gives indeed -1.
That was awesome. 
Keith (http://keithdevens.com/) wrote:
Your one bit of value 1 has to be converted to 32-bit integer. So it is padded with 1s and becomes 11111111 11111111 11111111 11111111, which in hex is FFFFFFFF which with printf("%x", 0xFFFFFFFF); gives indeed -1.
Yeah, that's what I said! 
Feel free to post a comment below. Please see my comment policy.
Formatting Rules (No HTML):
Generated in about 0.251s.
(Used 8 db queries)

The :1 in the struct sets the bit length of the field. Then you set it to 1, but it's a signed type, right? So all bits set true (where all = one of them) == -1.
So it should print -1.
And GCC (3.4) agrees with me
AGL