The Joy of
Programming Some Interesting Programming Puzzles
S.G. GANESH
Every experienced C programmer knows that if the code looks simple, straightforward and perfectly fine, it doesn’t necessarily mean that it would work fine and not dump-core at runtime! In this month’s column, we’ll look at a few such interesting programming problems. 1) This program had an assertion failure. Why? struct bitfield { signed int b : 1; } bit; int main() { bit.b = 1; assert(bit.b == 1); }
2) This function worked fine for many years and suddenly, for some value of i, the assertion failed. What was that value of i for which it failed and why? int my_abs(int i) { if (i < 0) { i = -i; } assert(i >= 0); return i; }
3) The following function was written with an intention that the printf should never be executed. But for some value of d, the message got printed! What is that value of ‘d’? void oops(double d) { if(d != d) printf(“Oops! Something went wrong”); }
4) The following program, when run, gave the output: sqrt of 2=1557547102.000000 instead of: sqrt of 2=1.414214. What could be the problem? int main() { double x = sqrt(2); printf("sqrt of 2=%lf", x); }
5) This program core-dumped at runtime instead of printing “hi”; can you find out why?
Avoid looking at the answers immediately; instead, try to solve them first. Solution 1: A signed bit-field size of 1 can store only one bit, and that value becomes a sign bit. For storing the value 1, the only bit available is used, which is the sign bit. So, 1 becomes -1 for a bit-field member of size 1. If you use “printf(“%d”, bit.b)”, you would see the output -1. Solution 2: This condition fails when i is INT_MIN. Remember that the range of an integer is 2(n-1) to 2(n-1)-1, where n is the size of the integer. INT_MIN is the least possible value of integral negative numbers and when we negate it, as in -i, it is not in the range of positive integers. So, it ‘overflows’ and becomes negative and INT_MIN again! So the assertion fails. Solution 3: For NaN (Not a Number), the condition (d == d) is not true! The IEEE 754 floating point arithmetic standard has a special number called NaN for representing invalid values like (0.0/0.0) instead of just throwing an error/exception like Divide-by-Zero. To detect this special number programmatically, the special condition of (NaN != NaN) is provided. Solution 4: The prototype for the sqrt library function is missing in this program. For those functions that are not declared (but used), the compiler assumes the return type to be int. Since <math.h> is not included in this program (which has the prototype for sqrt), sqrt is assumed to return int; the actual double value that is returned from sqrt(2) is converted to an int value and assigned to x after casting it to double. This results in the wrong output. The solution is to either use #include <math.h> or provide the prototype of sqrt before its use. Solution 5: The character ‘hi’ is a multi-byte character, and the programmer has typed ‘hi’ instead of “hi” (typing ‘, instead of “ , by mistake). The printf function tries to interpret msg as if it is pointing to a string literal, and reads that address, which is grossly incorrect; hence the program core-dumped... That’s it for now. And here’s wishing you a happy new year! S G Ganesh is a research engineer in Siemens (Corporate Technology). His latest book is “60 Tips on Object Oriented Programming”, published by Tata-McGraw Hill in December, 2007. You can reach him at
[email protected].
int main() { char * msg = ‘hi’; printf(msg); }
www.linuxforu.com
CMYK
|
LINUX FOR YOU
|
JANUARY 2008
127