c - 是否可以将两个具有不同签名的函数作为参数传递给另一个函数?

标签 c function-pointers

目前,我有以下2个功能:

void write_to_file(FILE *fp)
{
    fprintf(fp, "stuff here: %d", 10);
    /* 1000s of similar lines below */
}

void write_to_string(char *str)
{
    sprintf(str, "stuff here: %d", 10);
    /* 1000s of similar lines below */
}

我想将它多变形为一个函数。 我想过类似的事情:

void write_somewhere(void *ptr, int to_file)
{
    if (to_file) {
        typedef fprintf myprintf;
    } else {
        typedef sprintf myprintf;
    }
    myprintf(ptr, "stuff here: %d", 10);
}

这行不通而且看起来很丑。

由于fprintfsprintf的签名不同,如下,

int fprintf(FILE *stream, const char *format, …);
int sprintf(char *buffer, const char *format, …);

是否可以做类似的事情,

void write_somewhere(void *ptr, void *func)
{
    func(ptr, "stuff here: %d", 10);
}

编辑: 根据以下 Alter 的回答,这就是我所拥有的,但它并没有按预期工作,并且在尝试打印出 write_somewhere() 函数中的值时打印出垃圾值:

#include <stdio.h>
#include <stdarg.h>

typedef int (*myprintf_t) (void *, const char *, ...);

int myfprintf(void *ptr, const char *format, ...)
{
    va_list args;
    int ret;

    va_start(args, format);
    ret = vfprintf(ptr, format, args);
    va_end(args);
    return ret;
}

int mysprintf(void *ptr, const char *format, ...)
{
    va_list args;
    int ret;

    va_start(args, format);
    ret = vsprintf(ptr, format, args);
    va_end(args);
    return ret;
}

void write_somewhere(void *ptr, myprintf_t myprintf, const char *format, ...)
{
    va_list args;
    int ret;

    va_start(args, format);
    ret = myprintf(ptr, format, args);
    va_end(args);
    return ret;
}

int main(void)
{
    char s[100];
    int i = 100;

    /* This works */
    write_somewhere(stdout, myprintf, "Hello world");

    /* This prints out garbage */
    write_somewhere(stdout, myprintf, "Hello world, I am %d", i);
    write_somewhere(s, mysprintf);
    return 0;
}

最佳答案

Jen 的回答是正确的,但在这种情况下,您可以使用指向函数的指针将 ptr 重定向到 v*printf:

#include <stdio.h>
#include <stdarg.h>

int myfprintf(void *ptr, const char *format, ...)
{
    va_list args;
    int ret;

    va_start(args, format);
    ret = vfprintf(ptr, format, args);
    va_end(args);
    return ret;
}

int mysprintf(void *ptr, const char *format, ...)
{
    va_list args;
    int ret;

    va_start(args, format);
    ret = vsprintf(ptr, format, args);
    va_end(args);
    return ret;
}

void write_somewhere(void *ptr, int (*myprintf)(void *, const char *, ...))
{
    myprintf(ptr, "stuff here");
}

int main(void)
{
    char s[100];

    write_somewhere(stdout, myfprintf);
    write_somewhere(s, mysprintf);
    return 0;
}

上次编辑:

似乎你想传递一些额外的参数给write_somewhere,在这种情况下我建议:

#include <stdio.h>
#include <stdarg.h>

#define TO_FILE 0
#define TO_STRING 1

void write_somewhere(int where, void *ptr, const char *format, ...)
{
    #define myprintf(ptr, ...) \
    (where == TO_FILE ? vfprintf(ptr, __VA_ARGS__) : vsprintf(ptr, __VA_ARGS__))

    va_list args;
    va_start(args, format);
    myprintf(ptr, format, args);
    /* more stuff */
    va_end(args);
    #undef myprintf
}

int main(void)
{
    char s[100];

    write_somewhere(TO_FILE, stdout, "%u\n", 10);
    write_somewhere(TO_STRING, s, "Hello");
    printf("%s\n", s);
    return 0;
}

关于c - 是否可以将两个具有不同签名的函数作为参数传递给另一个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26419036/

相关文章:

c - 如何使 valgrind 仅报告与规则匹配的错误

c - 将 C 回调(没有上下文)包装到 Swift 闭包中

c++ - Boost 快速池分配器有函数指针问题?

c++ - 纯虚拟方法 VS。函数指针

c - 如何返回一个指向函数稍微修改版本的指针?

在 C 代码中创建输出单词数、不同单词数和最频繁出现的单词

c - 你如何在 const-correctness 下实现 strtol?

将 Char* 与 C 中的 Enum 变量进行比较

c - Visual Studio 2008 链接器希望解析所有符号,而不仅仅是使用过的符号

javascript - 如何在 Javascript 命名空间脚本中创建函数数组