Richard said:
You can only use #undef on macros. If your function name has been
#declared as a macro, this will work (FSVO - see below); if it has been
declared as an ordinary function declaration, it will do nothing.
This, however, you can always do. It's hairy, though.
None. Except that it will never actually be refered to in your code, so
will probably not be linked into the executable.
The macro trick, yes. In fact, a compiler's Standard headers often do.
What you cannot portably do is to define a _function_ with the same name
as a library function. Macros, however, are allowed. And even hairier
than re-#defining your own functions. Caveat hacker!
If the goal is to replace a Standard function with
your own implementation, note that the macro can only
affect code that is compiled with the macro definition
in place. If your code calls log() and you use a macro
to have it call my_log() instead, that's fine -- but if
the implementation of pow() calls log(), it will still
use log() and not my_log().
In my experience, wholesale overriding of function
names (from the Standard library or from elsewhere in
your own program) is a quick-and-dirty approach. It's
quick and convenient, but eventually the dirt will show.
Better to edit your source so it calls my_log() explicitly;
you'll probably wind up doing so eventually anyhow.
Horror story from a large program I once worked with:
The system-provided malloc() and friends performed poorly
with the amount of memory we used and the patterns in which
it tended to get fragmented. Some bright laddie solved the
problem by implementing a memory-management package more
suited to our program's habits of memory usage, and then
used macros to rename all the malloc(), free(), ... calls
so they went to the replacement package instead. Fine.
... for a while. Then somebody else observed that in
one subsystem of the program there was an atypical pattern
of memory use, where the original malloc() worked better
than the replacement. He added #undef's to the appropriate
set of modules, so calls to malloc() and friends within that
subsystem went to the "real" library while those in other
parts of the program went to our replacement versions. Still
fine.
... for a while longer. Then we decided to add a user-
accessible scripting language to the product, and this entailed
going into all the subsystems and adding various kinds of hooks
to register a system's callable services, provide for callbacks
to user-supplied functions, and so on. Naturally, a lot of
these things involved dynamically-allocated memory -- and when
Subsystem A obtained memory from the "real" malloc() and handed
it to Subsystem B, and then B tried to resize it with the
replacement realloc() ... Well, that's when the fertilizer
hit the air circulator.
Use the #define technique for quick-and-dirty hacks like
introducing instrumented versions during debugging, but don't
rely on it for "serious" code. The code *will* develop, and
the fakery *will* eventually make more trouble than it saved.