DanielH
DanielH

Reputation: 73

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

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

Answers (3)

Oliver Charlesworth
Oliver Charlesworth

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

pmg
pmg

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

Yann Vernier
Yann Vernier

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

Related Questions