KBD

Keith Devens .com

Tuesday, December 2, 2008 Flag waving
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.... – Ferris Bueller
← The Small languageWilliam Safire: After Arafat, Hope →

Daily link icon Thursday, November 11, 2004

C Puzzle

I don't know the answer to Steve's C puzzle, do you?

Actually, the code gives different answers on different compilers.

Update: Here's the puzzle, in case Steve's site doesn't exist forever (or, at least as long as this one does Smiley)

What does this code print? (hint: it's not 1):

struct { int a : 1; } b;
int i;
b.a = 1;
i = b.a;
printf("%i", i);

← The Small languageWilliam Safire: After Arafat, Hope →

Comments XML gif

Adam Langley (http://www.imperialviolet.org) wrote:

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 Smiley

AGL

∴ Adam Langley | 11-Nov-2004 5:39am est | http://www.imperialviolet.org | #6338

Keith (http://keithdevens.com/) wrote:

You win! Smiley

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 | 11-Nov-2004 11:38am est | http://keithdevens.com/ | #6339

Keith Gaughan (http://talideon.com/) wrote:

1 or -1 depending on whether the compiler uses signed or unsigned ints.

∴ Keith Gaughan | 11-Nov-2004 11:58am est | http://talideon.com/ | #6340

Keith (http://keithdevens.com/) wrote:

I thought ints were always supposed to be signed in C unless you ask for unsigned?

Keith | 11-Nov-2004 12:17pm est | http://keithdevens.com/ | #6341

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.

∴ Aggelos | 11-Nov-2004 1:31pm est | http://users.uoi.gr/agorf/ | #6342

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 Gaughan | 15-Nov-2004 4:17pm est | http://talideon.com/ | #6352

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 | 16-Nov-2004 12:00am est | http://keithdevens.com/ | #6357

Keith Gaughan (http://talideon.com/) wrote:

I blame Microsoft! Smiley

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.

∴ Keith Gaughan | 16-Nov-2004 9:58am est | http://talideon.com/ | #6364

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?

∴ Aggelos | 26-Nov-2004 9:15pm est | http://users.uoi.gr/agorf/ | #6453

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.)

Keith | 27-Nov-2004 12:19am est | http://keithdevens.com/ | #6455

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'?

∴ Aggelos | 27-Nov-2004 4:24am est | http://users.uoi.gr/agorf/ | #6456

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.

Keith | 27-Nov-2004 4:56am est | http://keithdevens.com/ | #6457

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 | 27-Nov-2004 6:37am est | http://users.uoi.gr/agorf/ | #6458

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. Smiley

∴ Aggelos | 27-Nov-2004 7:42am est | http://users.uoi.gr/agorf/ | #6461

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! Smiley

Keith | 27-Nov-2004 11:25am est | http://keithdevens.com/ | #6462

Feel free to post a comment below. Please see my comment policy.

Formatting Rules (No HTML):

  • **bold**, *italic*, _underlined_, --strikeout--
  • "text"="url" creates a link, and URLs are auto-highlighted
  • Blockquote: Like e-mail, begin paragraph with > (greater-than sign)
  • Lists: begin paragraph with *,-, or + (unordered), or # (ordered)
  • Code block: ?!code:language=perl|php|sql|javascript|etc.{\n}...{\n}?!/code

:
(will be your IP address if blank)
: (optional)
(Will not be shown on site)

: (optional)
:

December 2008
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
28293031 



RSS feed RSS feed for Keith's Weblog
Atom feed Atom feed for Keith's Weblog
Weblog archive
Recent comments
  on 6 posts

Recent comments XML

new⇒Perl 6 1.0 in March?

Doh, my mistake. I'm aware of the​relation between Parrot and Rakudo​but I'...

Keith: Dec 2, 1:03am

Free image hosting sites

Well, TinyPic has this in its​FAQ:

> Images and videos is in​your accoun...

Keith: Dec 1, 1:13am

Join a NameValueCollection into a querystring in C#

Well with a lamba expression, this​is what I came up​with:

?!code:csharp...

Gustaf Lindqvist: Nov 30, 4:38pm

Why no generic OrderedDictionary?

Check​http://www.codeproject.com/KB/recip​es/GenericOrderedDictionary.aspx?d...

Gabrielk: Nov 27, 6:57am

WhatIsMyIP.com

http://www.thesysteminfo.com is​another good alternate to​whatismp.com... I...

Kripz: Nov 26, 8:51pm

Girls, please don't get breast implants

Actually I think it's sweet when a​man loves a woman whether she's big​or n...

218.186.12.228: Nov 26, 9:40am

Generated in about 0.251s.

(Used 8 db queries)

mobile phone