Allow me to begin with a simple code segment:
#include
int main(int argc, char** argv){
printf("%d\n%d\n", 100==true, 1==true);
int x = 100;
if(x)
printf("true\n");
else
printf("false\n");
}
Here the standard bool type has been included and thus the macros for true and false are able to be used, as C defines it: false = 0 and true = anything not 0. And thus the statement "100==true" should evaluate to true (or as the system defaults, a 1) as well as the statement "1==true" then we go into the if statement where if(x) is translated "if x is true, then do
So what happens when this code is compiled and ran? (compiled with "gcc testbool.c -o testbool")
max@iPseudogen:~/cTheory$ ./testbool
0
1
true
Why does this happen? I'm not entirely sure, but I assume its because the logical operator == does not logically compare in the same manor, or abide by the same rules, as an if statement comparison. I would also assume this could make for some interesting program run time characteristics if one was to use a bool returning function and expect C to follow its own rules about the bool type as stated above.
Next, something slightly more complicated and brings up the point of how a programmer who does not understand the inner workings of a system could fall into error by bad programming technique:
int *x;
void f(){
int y = 1;
x = &y;
}
void g(){
int y = 400;
}
void main(){
f();
printf("%d \n", *x);
g();
printf("%d \n", *x);
}
What happens when this is compiled and run? (" gcc stackframe.c -o stackframe.c")
max@iPseudogen:~/cTheory$ ./stackframe.c
1
400
Now, why would this give different output if the printf statements are verbatim?
When the function f() is called, the system puts its function call on the "call stack" and since the local int variable y is created within the function, its memory allocation is also performed in the stack space. Then x, an int pointer, is assigned the memory location of the local variable y the programmer has now saved the address to a position in the stack space. Why is this bad? Well, it is demonstrated in this example. When the next function call is made, the first function is now finished and popped off the stack, the memory space on the call stack is deallocated, in order to be used later by another function and the system does just that: it uses that space for the next function and (low and behold), it defines a local variable as well and places it in the memory location that the previous locally defined variable was held in. Thus, we have demonstrated the ability to alter a global variable by defining a local variable and assigning it a value. Why is this bad? Well, go write some large scale project and have this be one of the errors in it, debugging would be fun don't you think?
I must make a disclaimer that Derr was the one who came up with the code examples and all credit must be given to him, so uhmm... yeah, that was the disclaimer.
Are there more little interesting things like this? Of course, I'm sure there are C follies that Derr and I have never heard of, but these were the ones discussed on that day and found it interesting enough to blog about while I sit here on my couch with my Xubuntu powered iBookG4 bored out of my mind. Now are there tools out there to catch things like this in C code? Yeah, probably ... just thought this was good food for thought.
-Adam