#undef-ing in Practice?

c, c-preprocessor

Solution

What it does

If you read Plauger's The Standard C Library (1992), you will see that the `<stdio.h>` header is allowed to provide `getchar()` and `getc()` as function-like macros (with special permission for `getc()` to evaluate its file pointer argument more than once!). However, even if it provides macros, the implementation is also obliged to provid actual functions that do the same job, primarily so that you can access a function pointer called `getchar()` or `getc()` and pass that to other functions.

That is, by doing:

#include <stdio.h>
#undef getchar

extern int some_function(int (*)(void));

int core_function(void)
{
   int c = some_function(getchar);
   return(c);
}

As written, the `core_function()` is pretty meaningless, but it illustrates the point. You can do the same thing with the `isxxxx()` macros in `<ctype.h>` too, for example.

Normally, you don't want to do that - you don't normally want to remove the macro definition. But, when you need the real function, you can get hold of it. People who provide libraries can emulate the functionality of the standard C library to good effect.

Seldom needed

Also note that one of the reasons you seldom need to use the explicit `#undef` is because you can invoke the function instead of the macro by writing:

int c = (getchar)();

Because the token after `getchar` is not an `(`, it is not an invocation of the function-like macro, so it must be a reference to the function. Similarly, the first example above, would compile and run correctly even without the `#undef`.

If you implement your own function with a macro override, you can use this to good effect, though it might be slightly confusing unless explained.

/* function.h */
…
extern int function(int c);
extern int other_function(int c, FILE *fp);
#define function(c) other_function(c, stdout);
…
/* function.c */

…

/* Provide function despite macro override */
int (function)(int c)
{
    return function(c);
}

The function definition line doesn't invoke the macro because the token after `function` is not `(`. The `return` line does invoke the macro.

Problem

I'm wondering about the practical use of #undef in C. I'm working through K&R, and am up to the preprocessor. Most of this was material I (more or less) understood, but something on page 90 (second edition) stuck out at me: Names may be undefined with `#undef`, usually to ensure that a routine is really a function, not a macro: `#undef getchar` `int getchar(void) { ... }` Is this a common practice to defend against someone `#define`-ing a macro with the same name as your function? Or is this really more of a sample that wouldn't occur in reality? (EG, no one in his right, wrong nor insane mind should be rewriting `getchar()`, so it shouldn't come up.) With your own function names, do you feel the need to do this? Does that change if you're developing a library for others to use?

Original source