我写的这段代码有些问题。海湾合作委员会不喜欢它:
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
但是gcc显示这个错误:
../debug.h:33:42: error: expected expression before ')' token
snprintf(buffer, size, string, __VA_ARGS__);
我阅读了关于variadic macro的gcc文档,我没有做错。
有人能指出我的错误吗?我完全迷失了。
编辑
我这样使用
_DEBUG_ADD("Bbox found @ %f %f %f %f", box[0], box[1], box[2], box[3]);
答案 0 :(得分:2)
如果我使用您显示的代码片段并填写缺失的位以获得完整的,可编译的源文件,我不会收到任何错误:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(double box[4])
{
_DEBUG_ADD("Bbox found @ %f %f %f %f", box[0], box[1], box[2], box[3]);
}
- &GT;
$ gcc -fsyntax-only -Wall test.c
$
这就是我们对minimal, complete, verifiable examples这么大惊小怪的原因。我们不想浪费大量时间咆哮错误的树。
然而,在这种情况下,我强烈怀疑您的问题实际上是由 this 等代码触发的:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(void)
{
_DEBUG_ADD("got here 1");
}
会产生几乎相同的错误消息:
$ gcc -fsyntax-only -Wall test.c
test.c: In function ‘test’:
test.c:11:43: error: expected expression before ‘)’ token
snprintf(buffer, size, string, __VA_ARGS__); \
^
test.c:21:3: note: in expansion of macro ‘_DEBUG_ADD’
_DEBUG_ADD("got here 1");
^~~~~~~~~~
当你在格式字符串之后给_DEBUG_ADD
没有参数时,__VA_ARGS__
会扩展为空,所以&#34;编译器正确&#34;认为
snprintf(buffer, size, string, );
这确实是语法错误。这就是GNU comma-deletion extension的用途:如果您将##
放在,
和__VA_ARGS__
之间,则当__VA_ARGS__
扩展为空时,将删除逗号。< / p>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, ##__VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(void)
{
_DEBUG_ADD("got here 1");
}
- &GT;
$ gcc -fsyntax-only -Wall test.c
$
不幸的是,此扩展仅适用于GCC和Clang。我理解C和C ++委员会正在讨论添加类似但不兼容的功能Real Soon Now(请参阅this question及其答案的评论,以及C委员会文档N2023和{{3} }),但即使他们这样做,也可能在此之前大约十年左右,无处不在。
顺便提一下,名称_DEBUG_ADD
以下划线开头。所有以下划线开头的名称至少在某些上下文中保留供C编译器和库内部使用。在您拥有很多语言经验之前,您不应该在代码中提供以下划线开头的名称。 (可以使用名称以下划线开头的内容,例如__VA_ARGS__
和_IONBF
,但前提是它们都有记录。)