I was learning about functions vs function-like macros in C.
Was reading the C Standard and I found this:
Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.185) The use of
#undef
to remove any macro definition will also ensure that an actual function is referred to.
So according to this, if I want to make sure get will be a function inside my code I have to access to the <stdio.h>
header file and enclose (I don't know if the function name or the macro name) in parenthesis or #undef
the macro?
I mean this: int (getc)(FILE *stream);
(or this? #define (getc)(...) )
or this:
#undef getc
But all this in the <stdio.h>
file?
Or is inside my code?
Can you give me an example on how to make sure to use getc
as a function in C?
As explained in the quoted paragraph, there is a simple way to prevent macro expansion of function-like macros defined in standard library headers: use the identifier not followed by an
(
introducing the argument list, eg: using parentheses around the identifier.For example:
Alternatively, you can undefine the macros before using the functions in your code. This will ensure that the preprocessor leaves the
getc
andputc
identifiers unchanged and the compiler will use their function declarations from<stdio.h>
.A simpler approach is to use the functions
fgetc
andfputc
which are guaranteed to behave as functions even if they may also be implemented as macros for performance:In any case, do not attempt to modify the standard headers, which should be read-only on modern systems.
Note also that the macro versions of the standard functions defined in
<stdio.h>
are only allowed to multi-evaluate the stream argument (the one corresponding to theFILE *
), not the character argument. Ancient systems where this was not guaranteed do not conform to any of the C Standards, and are completely obsolete. See for example the specification of theputc
function in the ISO C90 document:The final word is: don't worry about this and use the macros or the functions without hesitation, but don't pass an expression with side effects as the stream argument, which would be very cumbersome and error prone anyway.