0

Include guards in header files are often used to protect sections of code from double inclusion:

#ifndef FOOBAR_H
#define FOOBAR_H

extern void myfoofunc(void);

#endif

Include guards typically rely on the expectation that if an object-like macro was already defined, the lines within the #ifndef block will not included -- thus avoiding double inclusion.

I've noticed that the #define line for many include headers have empty replacement-lists. Does the C99 standard guarantee that object-like macros defined with an empty replacement-list will be considered "defined" by #ifndef?

When describing the syntax of #define, the C99 standard seems to imply that a replacement-list is required in section 6.10.3 paragraph 9:

A preprocessing directive of the form

# define identifier replacement-list new-line

defines an object-like macro that causes each subsequent instance of the macro name to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.

Does this mean include headers should instead be of the form: #define FOOBAR_H 1?

Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
  • "the C99 standard seems to imply that a replacement-list is required " -- It does no such thing. Take a look at the definition of replacement-list. – Jim Balter Jun 27 '13 at 21:45

3 Answers3

2

The standard syntax production for a replacement-list is: pp-tokens [opt]. So no tokens are necessary for a replacement-list to be valid.

So #ifdef will work fine and as expected for macros that are defined 'empty'. A ton of code depends on this.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Ah yes, I overlooked the *Syntax* listing in **section 6.10 paragraph 1**: `replacement-list` is defined as `pp-tokens [opts]` as you describe. – Vilhelm Gray Jun 27 '13 at 21:09
1

No, it doesn't. The replacement list may well be empty. #define FOO means that defined FOO is true, but FOO is replaced with nothing.

Example:

#define FOO
#define BAR 1

#if defined FOO && defined BAR
int a = FOO + BAR ;
#endif

Result of preprocessing:

int a = + 1 ;
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • In this case, would `#if FOO == 1` succeed, or is the actual numerical value of `FOO` implementation defined? – Vilhelm Gray Jun 27 '13 at 21:04
  • 1
    The value of `FOO` is the empty string. – Kerrek SB Jun 27 '13 at 21:06
  • Does this mean the I'd get a compiler error if I use `#if` to try to compare it to a numerical value? – Vilhelm Gray Jun 27 '13 at 21:11
  • @VilhelmGray: You would. (Why aren't you trying this out yourself?!) – Kerrek SB Jun 27 '13 at 21:17
  • I wasn't certain if this was just affecting my compiler, or should occur on all standard compliant compilers. For prosterity, I decided to verify this for C99 compliant compilers. In **section 6.10.1 paragraph 1**: `the resulting tokens compose the controlling constant expression which is evaluated according to the rules of 6.6`. So after macro replacement to an empty string we'd have `#if == 1`, thus leading to an improper constant expression and thus a compiler error on all C99 compliant compilers. – Vilhelm Gray Jun 27 '13 at 21:21
  • Oops, that should be "posterity" not "prosperity" in my original post. :P – Vilhelm Gray Jun 27 '13 at 21:25
  • 1
    @VilhelmGray "In this case, would #if FOO == 1 succeed" -- That expands to `#if == 1`. "the actual numerical value of FOO" -- there is no such thing ... the preprocessor does textual/token expansion. – Jim Balter Jun 27 '13 at 21:48
  • Posterity already has the C standard, it doesn't need quotations from it in SO comment threads. – Jim Balter Jun 27 '13 at 22:04
  • @JimBalter So does that mean that `#if FOO == 1` may be valid on certain compilers? – Vilhelm Gray Jun 27 '13 at 22:53
  • @VilhelmGray I have no idea why you would think that or how you could possibly get that from anything I wrote. FOO has an empty replacement-list, therefore "#if FOO == 1" expands to "#if == 1", which is a syntax error ... all of this is unambiguously specified by the C standard. – Jim Balter Jun 27 '13 at 22:57
0

No; the macro substitution will not take place in the #ifndef line. If it did, then the whole statement would be a syntax error (since there wouldn't be anything following the #ifndef).

I think I've actually seen some instances of #define FOOBAR_H 1 but that's more of a personal taste.

Drew McGowen
  • 11,471
  • 1
  • 31
  • 57