Reputation: 73
I was wondering whether there is anything wrong with passing a pointer to putchar, or any other standard function which can be implemented as a macro, to a function accepting a function pointer. Below is an example of what I'm doing.
#include <stdio.h>
static int print(const char *s, int (*printc)(int))
{
int c;
while (*s != '\0') {
if ((c = printc(*s++)) < 0)
return c;
}
return printc('\n');
}
int main(void)
{
print("Hello, world", putchar);
return 0;
}
I don't have any problems compiling this with GCC and Clang under GNU/Linux, as well as GCC under OpenBSD. I'm wondering whether it will have the same behaviour under every other standard compliant implementation, since putchar can be implemented as a macro. I've searched through the standard, particularly the sections on function pointers and putchar, and haven't been able to find anything that specifies whether this is legal or not.
Thanks.
Upvotes: 7
Views: 1084
Reputation: 272537
Following on from my comments-based discussion with @pmg, I found the relevant section of the standard (C99, 7.1.4 p.1):
... it is permitted to take the address of a library function even if it is also defined as a macro.161)
161) This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
Upvotes: 6
Reputation: 108938
The macro is only "invoked" when its identifier is followed by an open-parenthesis (
. Otherwise the real function of the same name is invoked/used.
#include <stdio.h>
#define macro(x) 42
int (macro)(int x) { return x; }
int main(void) {
printf("%d %d\n", macro(1), (macro)(1));
}
The function definition has "extra" parenthesis to prevent the macro from being expanded
See code running at ideone: http://ideone.com/UXvjX
Upvotes: 2
Reputation: 15887
It is legal, because it refers to the library function, not the macro. When it is defined as a macro, that macro takes an argument, and therefore putchar with no parenthesis following does not refer to it. This is an instance of using a macro to inline functions, and should not be taken as good practice now that inlining is supported by compilers.
Upvotes: 2