View Full Version : Preprocessor is evil
dave_
10-03-2005, 02:34 AM
One of my colleagues has just been got by a nasty little bug. We tracked it down to this sort of thing
#define SOME_DEFINE 1
... Some code
#if SOME_DEFINE == 0
... some more code
else
... something else
#endif
Whats the problem? Its the missing '#' infront of the else. It silently ignores all the code after the #if
.oisyn
10-03-2005, 04:57 AM
Preprocessors are good, they are excellent for build configuration settings and for multiplatform builds. We port games to/from pc, ps2 and xbox, and preprocessor directives are a great tool for supplying platform specific code.
Preprocessors aren't evil just because of the example you provided. There are tons of spelling errors in code that compile perfectly but don't do what's expected.
bladder
10-03-2005, 04:59 AM
anything without the '#' is not preprocessor code. And you've defined SOME_DEFINE as 1. So #if SOME_DEFINE == 0 is false and everything after that is ignored after the compiler, doesnt even try to compile it. So it will not catch the "else" mess up within the #if and #endif block. Try changing the SOME_DEFINE to 1 and it chould complain then.
leblebi
10-03-2005, 08:33 AM
By the same logic every command can be made evil:
for ( i=0;i<50;i++ );
printf ( "Now counting: %d\n", i );
NomadRock
10-03-2005, 09:01 AM
if you just changed that 50 to a 1 then it would be correct :)
bramz
10-03-2005, 12:54 PM
He is right though. The preprocessor _is_ evil (or better known as: macros are evil). That doesn't mean we don't want to use it though. It's a very powerfull tool, and we wouldn't want to go on without. But you must be carefull when playing with black magic :)
Bramz
baldurk
10-03-2005, 01:07 PM
By the same logic every command can be made evil:
for ( i=0;i<50;i++ );
printf ( "Now counting: %d\n", i );
if you just changed that 50 to a 1 then it would be correct :)
unless your code was very bad and you had another i variable outside the loop, it'd complain because i goes out of scope with the for loop.
.oisyn
10-03-2005, 04:09 PM
He is right though. The preprocessor _is_ evil (or better known as: macros are evil). That doesn't mean we don't want to use it though. It's a very powerfull tool, and we wouldn't want to go on without. But you must be carefull when playing with black magic :)
Bramz
Well yes, you shouldn't use macro's for things that should actually be constants or inline functions. But to say that the whole construct of macro's are evil... Otherwise exceptions would be evil too, as you can use them for normal program flow [and more of such examples] :)
unless your code was very bad and you had another i variable outside the loop, it'd complain because i goes out of scope with the for loop.
Look again, he doesn't define i inside the for statement ;)
NomadRock
10-03-2005, 05:30 PM
unless your code was very bad and you had another i variable outside the loop, it'd complain because i goes out of scope with the for loop.
you will notice that i was not declared in the loop, and you will also notice that he uses printf and so is probably using C which doesnt even allow you to declare variables inside the loop. The variable i is most likely declared at the beginning of the enclosing function
Maybe I am wrong but I think the “i” is not the point. It’s the semicolon after the for statement. It would be more readable like this:
for( i=0;i<50;i++)
;
printf( “Now counting: %d\n”, i );
witch is the same as:
for( i=0;i<50;i++)
{
;
}
printf( “Now counting: %d\n”, i );
or am I now missing something :)
NomadRock
10-03-2005, 06:18 PM
you are right moe, I was making a joke. but it *is* true that the output would be the same with or without the semicolon if the loop only went 0 to less than 1 anyway :)
dave_
10-04-2005, 02:28 AM
Cross platform and debug information (such as leak tracking and assertions) are the only things I use the preprocessor for. (I had to remove the code cos of NDAs)
I prefer to see the C++ code, incase you have to debug it. Its easier than having to export the generated code.
And while I'm at it, printf's aren't too good. They arent type-safe.
dave_
10-04-2005, 02:30 AM
By the same logic every command can be made evil:
for ( i=0;i<50;i++ );
printf ( "Now counting: %d\n", i );
I disagree. My IDE would change the indentation, making it a lot easier to spot.
bramz
10-04-2005, 02:39 AM
Well yes, you shouldn't use macro's for things that should actually be constants or inline functions. But to say that the whole construct of macro's are evil... Otherwise exceptions would be evil too, as you can use them for normal program flow [and more of such examples] :)
the "evil" thing is mostly used to make clear to former C programmers they should rethink how they use it. As such, macros, arrays, malloc, pointer casts are all evil ( http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15 ).
But of all those "evil" things, the preprocessor really is! That's why we have habits like using ALL_CAPS for macro names and for macro names only. So that there's a red flag saying to be extra carefull when using them (and not ending up having your variable min replaced by a very very evil windows.h macro). The preprocessor is pure black magic. Very powerfull if used wisely (what we do all the time of course :) ), but so dangerous in the wrong hands ...
Bramz
PS: if exceptions are evil, then every language construct is evil, so no, they're not :P
.oisyn
10-04-2005, 09:01 AM
you will notice that i was not declared in the loop, and you will also notice that he uses printf and so is probably using C which doesnt even allow you to declare variables inside the loop.
C99 does ;)
zavie
10-04-2005, 10:44 AM
PS: if exceptions are evil, then every language construct is evil, so no, they're not :P
What about pure functional languages? ;-P
Mihail121
10-04-2005, 11:00 AM
That's why i like C! It's evil and not evil in the same time!
davepermen
10-04-2005, 03:23 PM
the evil thing about the preprocessor is that it's just that: a preprocessor. it doesn't understand the language of the code, it doesn't care about it, and so does the compiler not care about the preprocessor parts.
they are individual, and both very different interpreting of the given code. the result: the preprocessor can change the way normally save code behaves, resulting in totally dangerous mess..
but thats why we love c and c++.. because somehow, it feels great to be part of that mess.. because we think we have it in our hands and control..
till the next crash :D
.oisyn
10-05-2005, 03:51 AM
PS: if exceptions are evil, then every language construct is evil, so no, they're not :P
Thank you for making my point ;)
leblebi
10-05-2005, 07:46 AM
In short, if you don't understand something (and in your case you don't even know the syntax let alone understand it), don't accuse it of being evil. Preprocessor is not an exception to this.
The comment about how indentation will help you spot it or etc. is not the issue here since I use vi to write C/C++ code.
bramz
10-05-2005, 08:06 AM
Thank you for making my point ;)
no, macros are evil, exceptions not ;)
Reaper_Unreal
10-05-2005, 08:52 AM
You think that evil is usage, here's something I saw when I was working at a previous job in an unnamed company.
In frame/stdlib.h:
#include_next "stdlib.h"
In common/stdlib.h:
#ifdef USERSPACE
#include <stdlib.h>
#else
...defined own replacement functions here
#endif
Firgure that one out. Now THAT is evil, but was necessary for our transition from a kernel-space application to a user-space application. To be honest I've never had a use for include_next before, and I probably never will again.
Rydinare
10-05-2005, 09:18 AM
One of my colleagues has just been got by a nasty little bug. We tracked it down to this sort of thing
#define SOME_DEFINE 1
... Some code
#if SOME_DEFINE == 0
... some more code
else
... something else
#endif
Whats the problem? Its the missing '#' infront of the else. It silently ignores all the code after the #if
The code could've used a different tactic to avoid this problem. With the preprocessor, I try to avoid #else as the (everything else case) and, instead use #elif. So, make it something like this:
#define SOME_DEFINE 1
... Some code
#if SOME_DEFINE == 0
... some more code
#elif SOME_DEFINE == 1
... something else
#else // SOME_DEFINE has an invalid value
#error SOME_DEFINE has an invalid value
#endif
Now, even if you forgot the # on the else, you'd have the compiler's help in tracking it.
vBulletin, Copyright ©2000-2010, Jelsoft Enterprises Ltd.