Watch out for operator alternates
I'm doing some examples for the next instalment of my Quality Matters column for ACCU's Overload, and got caught by a head-scratcher that someone who's been programming C and C++ for as long as I have has no right to forget. See if you can spot the problem.
At the moment, I'm writing a set of instalments examining exceptions. One of the issues I'm covering is under what conditions it's possible to assert that a program must succeed, as opposed to those in which success may be assumed for the majority of conditions, or those in which success may not be assumed and contingent action taken. I give a couple of examples of programs that can be asserted, by inspection, to never fail, and for which it is therefore reasonable to return 0.
Author diligence - read "paranoia" and "experience", having been caught out with embarassing syntax errors in published works before - compelled me to compile them, even though I knew they were right: they were so simple, after all. Well, of course, I was caught out. When compiling the following code, Borland, Visual C++ and CodeWarrior were all happy as a dog with a stick. GCC, however, gave me a weird, and temporarily discombobulating, compile error: ..\hello-world.4.c:2: error: expected unqualified-id before '!' token
/* hello-world.4.c */
<strong>int not(int v)</strong>
{
return !v;
}
int main()
{
return not(1);
}
The way I tend to look at compile errors is to look at the line, before even considering the nature of the error. So, I looked at the line, which is obviously ok. Then I considered the details of the error, which pertain to the ! symbol, but that doesn't appear until line 4. Hmmm. Confusion.
What caused me to "get it" within a minute or two was the fact that with all other compilers I tried (incl. Borland, CodeWarrior, and Visual C++) it all worked fine. So it must be something GCC. And then I remembered having hit this before, though with and rather than not.
What's happpening here is that GCC is being more eager in tis standards-compliance than the others in this respect. The C standard specifies (in clause 7.9) a number of alpha-only symbols that are to be replacements for various logical and bitwise operators, to account for programming environments where the operator symbols are not readily available. The symbols are shown in the following table.
and | && | |
and_eq | &= | |
bitand | & | |
bitor | | | |
compl | ~ | |
not | ! | |
not_eq | != | |
or | || | |
or_eq | |= | |
xor | ^ | |
xor_eq | ^= |
The requisite #defines reside within the standard header iso646.h. With the other compilers, you have to include them explicitly in order to encounter the conflict. GCC is just being more eager, in righteously policing the use of symbols that are reserved whether you declare you want to use them or not. And that's a good thing. Yet another reason why you should always try to compile your C and C++ code with multiple compilers.
Out of interest, if you wish to verify this with Visual C++, save the above program code to hello-world.4.c and then execute the command-line:
cl -FIiso646.h -nologo hello-world.4.c
The -FI option forces the inclusion of the named header, which can be a neat thing from time to time.

