【问题标题】:getting error: expected declaration specifiers or '...' before string constant出现错误:字符串常量之前的预期声明说明符或“...”
【发布时间】:2019-12-29 06:26:41
【问题描述】:

我正在尝试创建一个日志函数,该函数将采用日志类型 msg 并将添加文件名、函数名、调用日志函数的行。我创建了以下测试代码,但出现了我不理解的错误

#include<stdio.h>

#define func(type, msg, ...) func(type, __FILE__, __func__, __LINE__, msg, __VA_ARGS__)

void func(int type, const char *file, const char *function, int line, const 
          char *msg, ...)
{
     printf("%s",msg);
}

main()
{
    func(10,"time");
}

这里是错误日志:

||=== Build file: "no target" in "no project" (compiler: unknown) ===|
E:\code\C code\A.c|6|error: expected declaration specifiers or '...' before string constant|
E:\code\C code\A.c|3|error: expected declaration specifiers or '...' before '__func__'|
E:\code\C code\A.c|6|note: in expansion of macro 'func'|
E:\code\C code\A.c|6|error: expected declaration specifiers or '...' before numeric constant|
E:\code\C code\A.c|6|warning: type defaults to 'int' in declaration of 'msg' [-Wimplicit-int]|
E:\code\C code\A.c|3|note: in definition of macro 'func'|
E:\code\C code\A.c|12|warning: return type defaults to 'int' [-Wimplicit-int]|
E:\code\C code\A.c||In function 'main':|
E:\code\C code\A.c|3|warning: implicit declaration of function 'func' [-Wimplicit-function- 
declaration]|
E:\code\C code\A.c|15|note: in expansion of macro 'func'|
E:\code\C code\A.c|3|error: expected expression before ')' token|
E:\code\C code\A.c|15|note: in expansion of macro 'func'|
||=== Build failed: 4 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|

我已阅读此question,但无法将解决方案与我的代码联系起来。

【问题讨论】:

  • 函数名func 替换为您的定义。
  • const *msg -> const char *msg
  • 将 char *func 更改为 char *fnc 后错误仍然存​​在
  • FILE&lt;stdio.h&gt; 中的一个类型(或者,至少,FILE * 是)。那可能会把事情扔掉。我建议你应该在函数中使用const char *file(添加const 并重命名它。为了一致性,也将LINE 重命名为小写line
  • 建议将void func(int type, char *FILE, char *fnc, int LINE, const cahr *msg, ...) 替换为void (func)(int type, const char *file, const char *function, int line, const char *msg, ...)func 周围的括号防止它被视为宏的调用。我会使用function 而不是fnc,但是YMMV。我也可能将msg 重命名为fmt — 看起来它可能是printf() 系列函数之一的格式字符串(实际上是vprintf() 系列之一)。而且我可能会为函数使用一个比func 更有意义的名称。

标签: c gcc compiler-errors macros


【解决方案1】:

您的代码可能是:

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

extern void (logger)(int type, const char *file, const char *function, int line, const char *fmt, ...);

#define logger(type, msg, ...) logger(type, __FILE__, __func__, __LINE__, msg, __VA_ARGS__)

void (logger)(int type, const char *file, const char *function, int line, const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    printf("%s:%d:%s() - %d: ", file, line, function, type);
    vprintf(fmt, args);
    va_end(args);
}

int main(void)
{
    logger(10, "time %ld\n", (long)time(0));
}

需要额外的参数,以便__VA_ARGS__ 可以引用。请参阅#define macro for debug printing in C 进行广泛讨论。最简单的可移植修复可能是更改宏以将格式字符串包含为__VA_ARGS__ 的一部分。

#define logger(type, ...) logger(type, __FILE__, __func__, __LINE__, __VA_ARGS__)

通过此更改,您可以再次使用它:

int main(void)
{
    logger(10, "time\n");
}

最好将人们将使用的宏名称 (logger) 与函数名称分开(例如 logger_locloc 表示“位置”信息)。但是,如果他们希望直接调用该函数,有认识的用户可以写(logger)(10, "elephants.c", "pachyderm", 31921, "time\n");。因为logger 后面没有紧跟( 标记,所以它不是函数类宏logger 的调用。

对于“缺少__VA_ARGS__”问题,还有一个特定于 GCC 的解决方法,C++20 也解决了这个问题并产生了一个不同的解决方案(参见Portably detect __VA_OPT__ support?),我预计这很可能会出现在未来的 C 标准中(以及出现在假设的未来 C 标准之前的 C 编译器中)。

【讨论】:

  • 当我调用不带可变长度参数 logger(10, "time") 的记录器函数时,它不起作用;
  • 哪个版本不工作?我说的那个不行,还是我说的那个行?因为坦率地说,如果你声称我所说的版本将在 type 信息(即宏 #define logger(type, ...) logger(type, __FILE__, __func__, __LINE__, __VA_ARGS__))之后仅使用像 "time\n" 这样的简单参数时,我将很难相信你实际上并没有工作。您必须提供证明——如果需要,您可以向我发送电子邮件(请参阅我的个人资料)以及您的代码。另外,请阅读其他问题;它也经历了必要的事情。
  • 我在阅读您的代码后尝试自己实现它,但我忘记删除宏中的味精。您的代码运行良好,感谢您的解决方案。
  • 这里是宏和函数定义#define log_msg(type, ...) log_msg(type, FILE, func, LINE, VA_ARGS) void (log_msg)(int type, const char *fileName, const char *functionName, int line, const char *fmt, ...);当我在 Windows 中运行它时,这工作正常,但是当我将相同的代码放在 openwrt(基于 unix 的路由器操作系统)中时,它会给出以下错误错误:')' 标记之前的预期表达式 #define log_msg(type, ...) log_msg(type, FILE, func, LINE, VA_ARGS) 为什么会这样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 2011-09-04
  • 2014-06-08
相关资源
最近更新 更多