Wednesday, July 20, 2011

Geek corner: A C puzzle

A bucket full o' bits to the first person who can correctly answer this question without actually running the program: what is the output of the following C program:


#include

main() {
unsigned int i = 0;
unsigned short s = 0;
int x = -1;
printf("%d %d\n", x>i, x>s);
}


Hint: It's not "0 0".

More info, particularly in the comments. Sometimes it's a wonder that anyone manages to write working code in C. (That anyone can write working C++ is nothing short of miraculous.)

10 comments:

Miles said...

I think John Carmack mentioned this on his twitter feed the other day. Isn't the trick that an unsigned short is automatically changed to be an unsigned int as well or something whacky like that?

Miles said...

Or am I looking at it the wrong way, and the int is being changed to an unsigned int?

Tony Mach said...

No directly related, but I had to think of this from the "things that can kill ya" department:
From C++ 03, 5.8/1: The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

http://blogs.msdn.com/b/larryosterman/archive/2011/02/11/the-case-of-the-inconsistent-right-shift-results.aspx

Miles said...

So I decided to test this, and in C/C++'s defense, I did get a 'signed/unsigned mismatch' warning when compiling it.

Not quite sure I understand the behaviour though, will have to think about this one.

Ron said...

You must not be using gcc:

[ron@mighty:~]$ cat foo.c
#include

int main() {
unsigned int i = 0;
unsigned short s = 0;
int x = -1;
printf("%d %d %d %d\n", x>i, x>s, i<x, s<x);
return 0;
}
[ron@mighty:~]$ gcc -Wall foo.c
[ron@mighty:~]$

less is more said...

The signed int is converted to unsigned int so (x>i) is true because 11111111 > 00000000 (to however many bits).

However, the unsigned short is converted to signed int so (x>s) is false because -1 < 0.

There is a sequence of rules to be followed and they make sense altogether.

a2800276 said...

@miles just out of curiosity, what compiler issues that warning?

less is more said...

Hopefully, all of them :) You're not supposed to compare signed and unsigned integers.

Unknown said...

the -Wextra flag gets the warning for me:

MYDEV:~$ gcc -Wall -Wextra test.c
test.c: In function ‘main’:
test.c:7: warning: comparison between signed and unsigned integer expressions
test.c:7: warning: comparison between signed and unsigned integer expressions

Deepak Surti said...

This is a problem related to (I would say 'invisible') conversions. In this case, for x > i, its converting the signed int to unsigned int.

I would say I only know its related to such magic tricks which I would never learn.

Refer to C99 standard, I go to sleep!

******

Now as a corollary, I programmed in C, C++ for first 2 years and thought I was good for nothing where programming was concerned. Then I ran away. I moved to Java. I was still good for nothing. Then I moved to Lisp for the past 2.5 years and I have never encountered such nightmares :-), though Lisp is not perfect; but at least no magic tricks.

I might work at McDonalds than program in C, C++.

******