向一个接收 int (*)(int) 的函数传递指向 putchar 的指针

7
我在想是否将指向putchar的指针,或任何其他可实现为宏的标准函数,传递给接受函数指针的函数是否有问题。以下是我正在进行的示例。
#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;
}

我在GNU / Linux下使用GCC和Clang,以及在OpenBSD下使用GCC编译时没有任何问题。 我想知道在每个其他符合标准的实现中是否会具有相同的行为,因为putchar可以实现为宏。 我已经搜索过标准,特别是函数指针和putchar的部分,但没有找到任何说明其是否合法的内容。
谢谢。

如果你的“函数”实际上是一个宏,那么你的代码将无法编译。 - Oliver Charlesworth
不确定是否符合标准,但在 gcc 中,这似乎是预期的行为:http://gcc.gnu.org/onlinedocs/cpp/Function_002dlike-Macros.html - RageD
3个回答

6

继我与@pmg的基于评论的讨论后,我发现了标准的相关部分(C99,7.1.4 p.1):

即使库函数也被定义为宏,也允许取其地址。161)


161) 这意味着,即使为该函数提供了一个宏,实现也应该为每个库函数提供一个实际的函数。


2

这是合法的,因为它引用的是库函数,而不是宏。当它被定义为宏时,该宏需要一个参数,因此没有跟随括号的 putchar 不会引用它。 这是使用宏内联函数的实例,并且现在由于编译器支持内联,不应将其视为良好的实践。


2
宏仅在其标识符后跟开括号(时被“调用”。否则,同名的实际函数会被调用/使用。
#include <stdio.h>
#define macro(x) 42
int (macro)(int x) { return x; }
int main(void) {
    printf("%d %d\n", macro(1), (macro)(1));
}

函数定义中有“额外”的括号,是为了防止宏被展开。
在ideone上查看运行的代码:http://ideone.com/UXvjX

确实如此。但我认为这并不能真正帮助楼主解决他的问题。 - Oliver Charlesworth
1
标准明确规定putchar必须是一个函数(也可以是宏),因此OP的代码是有效的。 - pmg
啊,没错,我刚才找到了标准的相关部分。 - Oliver Charlesworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接