C Puzzles
gowrikumar.com
gowrikumar.com
Here's one way, cheating a bit by abusing the definition of "a C program which prints":
/tmp$ gcc hw.c
hw.c:1:2: warning: #warning Hello world! [-Wcpp]
#warning Hello world!
A more serious solution, though: /tmp$ cat hw.c
#include <stdio.h>
void main(void)
{
if (puts("Hello world!")) {}
}
/tmp$ gcc hw.c
/tmp$ ./a.out
Hello world! int main(int args, char *argv[printf("Hello, world!")]) { }>It's not standards-compliant
Why? It's just a VLA.
int main(void) { /* ... */ }
or int main(int argc, char *argv[]) { /* ... */ }>or equivalent; 10)
>10) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char * * argv, and so on.
And Standard also says that:
>or in some other implementation-defined manner.
and:
>In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.
So main can be pretty much anything according to the Standard, depending on the system.
#include <stdio.h>
int main()
{
float a = 12.5;
printf("%d\n", a);
printf("%d\n", *(int *)&a);
return 0;
}
This program invokes undefined behaviour when it casts float\* to int\*, so technically it could print anything, or do something else. I'm not sure how using memcpy instead would impact the puzzle's point though.Also these are C puzzles and casting pointers to incompatible types and dereferencing them is undefined behavior. Using memcpy would indeed fix this according to e.g. [1].
[1] http://blog.llvm.org/2011/05/what-every-c-programmer-should-... (section "Violating Type Rules")
To predict the outcome one have to know the representation of float (IEEE 754) and the big/little endian issues which could be different between floats and ints.
printf("%d\n", a) does promote the value a to a double first (promotion rules) and then either the first or last part i(assuming sizeof(double) == 2*sizeof(int)) is shown depending on little or big endian architecture.
Reinterpreting an object as an incompatible object is undefined. int and float are incompatible.
C Standard also specifically states that using an incorrect printf format specifier will result in undefined behavior.
On x86-64, it displays a random value each time, which actually happens to be some pointer (randomised by ASLR). This is because register passing is used on x86-64, and the the double is stored into a floating point register, but %d reads from a different register.
printf("%d\n", * (int*)&a); produces the number 1095237632 for both x86 and x86-64.
http://students.mimuw.edu.pl/~dj189395/nhp/czynic/programy/t...
Also:
> What's the output of the following program. (No, it's not 10!!!)
What's the point of including a program that calls malloc without including a prototype for it, after asking the reader earlier answer why such a program segfaults on IA-64 but not IA-32?
(The answer is: a constraint is violated, requiring a diagnostic, because an int * object pointer is assigned the return value of malloc whose implicit declaration marks it as returning int. The comment issue is a red herring.)