Saturday, November 27, 2010

Why are my zeroes behaving like ones?

Guess the output of this program:

C:\>type x.c
#include <stdio.h>
#define ZERO 0
#define P(x) printf("x=%d",x)
main()
{
P(ZERO);
}

C:\>.\x.exe
x=1

Duh, what?

Ok, I cheated, I didn't show you the stupid compiler option I managed to pass through the use of a slightly buggy makefile.

C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

For those who don't memorise command-lines, that /D0 essentially is instructing the compiler to "define a value for the symbol 0" and the default value for definitions is "1".

Yes, the Microsoft VC90 compiler actually allows you to redefine the value of INTEGER tokens in your source code. Same thing happens at VC100.

C:\>cl /D0 x.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

x.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:x.exe
x.obj

C:\>.\x.exe
x=1

It could be argued that it only shows up if you have one preprocessor macro using the value of another preprocessor macro, and you have to use an unlikely command-line option, so its not that tragic. But seriously guys, Apple catches you doing that sort of stupid thing at command-line parsing time...

jeff$ cc -D0 x.c
<command-line>: error: macro names must be identifiers

... and those of that that grew up with ANSI-C use macros like this all the time.

#define NAME(l) l[0]
#define ADDR(l) l[1]
#define TYPE(l) l[2]

Having those 0, 1 and 2 become subject to the whim of the command-line is unthinkable.

This all came about because of a Python-generated command line. I thought I was creating

CL /DOPTION0 x.c

but a bug meant I created this instead:

CL /DO /DP /DT /DI /DO /DN /D0 x.c

So I'm a lot more careful now.

Someone did point out to me that "All computer programs are just 0s and 1s. Looks like this one was just 1s".

Computer geek humor.