Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中带参数展开的自定义打印函数的变量宏_C - Fatal编程技术网

C语言中带参数展开的自定义打印函数的变量宏

C语言中带参数展开的自定义打印函数的变量宏,c,C,我正在尝试为我的应用程序复制printf。我没有使用stdout,而是使用了一组不同的用户特定指针,它们基本上指向要打印内容的位置。因此,我们没有: #define print(fmt, ...) printf(stdout, fmt, __VA_ARGS__) 我想要这样的东西: #define print(x, fmt, ...) dev_printf(x->pointer_to_a_screen, fmt, __VA_ARGS__) 这里的期望是x是一个存储用户当前上下文和信息的

我正在尝试为我的应用程序复制printf。我没有使用stdout,而是使用了一组不同的用户特定指针,它们基本上指向要打印内容的位置。因此,我们没有:

#define print(fmt, ...) printf(stdout, fmt, __VA_ARGS__)
我想要这样的东西:

#define print(x, fmt, ...) dev_printf(x->pointer_to_a_screen, fmt, __VA_ARGS__)
这里的期望是x是一个存储用户当前上下文和信息的结构。我想自动展开x,使用指向屏幕的指针,它基本上告诉dev_printf在哪里打印给定的输入。期望是dev_printf需要像任何其他标准printf函数一样工作,用户可以指定变量参数


这可能吗?我不断得到一个以上定义打印编译错误反复,我不明白为什么?我无法展开第一个参数?

我不会使用宏来展开

int mystrangeprintf(MYTYPE *x, const char *fmt, ...)
{
    int length;
    char buff[256];
    va_list va;
    va_start(va, fmt);
    length = vsnprintf(buff, sizeof(buff), fmt, va);
    va_end(va);
    dev_printString(x->pointer_to_a_screen, buff);
    return length;
}

我不会为此使用宏

int mystrangeprintf(MYTYPE *x, const char *fmt, ...)
{
    int length;
    char buff[256];
    va_list va;
    va_start(va, fmt);
    length = vsnprintf(buff, sizeof(buff), fmt, va);
    va_end(va);
    dev_printString(x->pointer_to_a_screen, buff);
    return length;
}

如果未传递任何参数,则必须删除尾随逗号。即

#define print(x, fmt, ...) dev_printf(x->pointer_to_a_screen, fmt, __VA_ARGS__)
print(something, "arg: %d", i); 
// expands to dev_printf(something->pointer_to_a_screen, "arg: %d", i); 
// all fine
// but:
print(something, "no arg"); 
// expands to dev_printf(something->pointer_to_a_screen, "not arg", ); 
//                                                                ^^
在您的情况下,您可以:

#define print(x, ...) dev_printf(x->pointer_to_a_screen, __VA_ARGS__)
较新的代码应使用_VA_OPT__uuu:

在uuu VA_uopt_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

您还可以使用POSIX创建一个自定义流,可以使用普通的fprintf函数对其进行操作

每个标准*printf函数都具有等效的v*printf函数。最好是提供您自己的dev_vprintf函数,该函数将接受一个va_列表,然后提供一个简单的包装器:

#ifdef __GNUC__
// ex. on gcc compiler this causes printf-like warnings to happen
__attribute__((__format__(__printf__, 2, 3)))
#endif
return_type print(some_type *x, const char *fmt, ...) {
   va_list va;
   va_start(va, fmt);
   return_type e = dev_vprintf(x->pointer_to_a_screen, fmt, va);
   va_end(va);
   return e;
}

这样的包装器将检查类型不匹配,易于维护,并且易于检查错误。

如果没有传递参数,则必须删除尾随逗号。即

#define print(x, fmt, ...) dev_printf(x->pointer_to_a_screen, fmt, __VA_ARGS__)
print(something, "arg: %d", i); 
// expands to dev_printf(something->pointer_to_a_screen, "arg: %d", i); 
// all fine
// but:
print(something, "no arg"); 
// expands to dev_printf(something->pointer_to_a_screen, "not arg", ); 
//                                                                ^^
在您的情况下,您可以:

#define print(x, ...) dev_printf(x->pointer_to_a_screen, __VA_ARGS__)
较新的代码应使用_VA_OPT__uuu:

在uuu VA_uopt_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

您还可以使用POSIX创建一个自定义流,可以使用普通的fprintf函数对其进行操作

每个标准*printf函数都具有等效的v*printf函数。最好是提供您自己的dev_vprintf函数,该函数将接受一个va_列表,然后提供一个简单的包装器:

#ifdef __GNUC__
// ex. on gcc compiler this causes printf-like warnings to happen
__attribute__((__format__(__printf__, 2, 3)))
#endif
return_type print(some_type *x, const char *fmt, ...) {
   va_list va;
   va_start(va, fmt);
   return_type e = dev_vprintf(x->pointer_to_a_screen, fmt, va);
   va_end(va);
   return e;
}

这种包装器将检查类型不匹配,易于维护,并且易于检查错误。

如果您遇到错误,请在问题中包含准确的错误文本。您仍然可以编辑以将其放入其中。听起来很像。@tadman这个错误在我这边是个错误。后来我意识到这很愚蠢。我会确保在下一篇文章中包含它。谢谢你指出。如果你有错误,请在你的问题中包含准确的错误文本。您仍然可以编辑以将其放入其中。听起来很像。@tadman这个错误在我这边是个错误。后来我意识到这很愚蠢。我会确保在下一篇文章中包含它。谢谢你指出。谢谢你的解释。我不太清楚尾随的逗号错误。谢谢你的其他建议。我想我想要一些类似fopencookie的东西,但我认为使用fopencookie作为一个整体解决方案会是一个更好的选择。看来我的实现过于复杂了。。。再次感谢你的回答!谢谢你的解释。我不太清楚尾随的逗号错误。谢谢你的其他建议。我想我想要一些类似fopencookie的东西,但我认为使用fopencookie作为一个整体解决方案会是一个更好的选择。看来我的实现过于复杂了。。。再次感谢你的回答!