Passing a pointer to putchar to a function receiving int (*) (int)

I was wondering if there is something wrong with passing a pointer to putchar or any other standard function that can be implemented as a macro of a function that takes a pointer to a function. Below is an example of what I am 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 have no problem compiling this with GCC and Clang under GNU / Linux, as well as GCC under OpenBSD. I am wondering if it will have the same behavior with every other standard compatible implementation, since putchar can be implemented as a macro. I was looking at the standard, especially the function pointer and putchar sections, and could not find anything that indicates whether this is legal or not.

Thanks.

+7
source share
3 answers

After my discussion based on comments with @pmg, I found the appropriate section of the standard (C99, 7.1.4 p .1):

... it is allowed to accept the address of a library function, even if it is also defined as a macro. 161)


161) This means that the implementation must provide an actual function for each library function, even if it also provides a macro for that function.
+6
source

This is legal because it refers to a library function, not a macro. When it is defined as a macro, this macro takes an argument, and therefore putchar without parentheses does not refer to it. This is an instance of using macros for built-in functions, and now it cannot be taken as good practice when built-in support is supported by compilers.

+2
source

A macro is only "called" when its identifier is followed by an open bracket ( . Otherwise, a real function with the same name is called / 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)); } 

Function definition has β€œextra” parentheses to prevent macro expansion

See the code running on ideone: http://ideone.com/UXvjX

+2
source

All Articles