为什么宏不能使用静态函数?

时间:2019-02-03 17:04:44

标签: c static

我正在看这个github logger project,并且在我自己的环境中尝试它。我试图将函数log_log更改为static,以便无法在其他文件中调用它,并且会强制“用户”(me)仅使用宏。

当我将函数更改为静态时,即使宏应该能够看到它,我也会在main中获得未定义的引用。为什么是这样?有没有办法做到这一点?

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

#define LOG_VERSION "0.1.0"

typedef void (*log_LockFn)(void *udata, int lock);

enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };

#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

void log_set_udata(void *udata);
void log_set_lock(log_LockFn fn);
void log_set_fp(FILE *fp);
void log_set_level(int level);
void log_set_quiet(int enable);

void log_log(int level, const char *file, int line, const char *fmt, ...);

3 个答案:

答案 0 :(得分:3)

由于未在标头中定义log_log函数,因此出现“未定义引用”链接器错误;它只是声明。 (请参见Understanding the difference between definining and declaring a variable;这些概念在声明和定义函数时类似。)

说函数是static,就是说log_log()将在定义main()函数的源文件中定义,并且还将分别定义在任何其他尝试调用它的文件中(除非该函数很简单,否则这将是浪费的)。但是定义不存在,因此在链接程序时会收到“ undefined reference”消息。使用默认的编译器选项,编译器(而不是链接程序)也会通知我,未定义声明为static函数的函数。

如果不经过诸如包含包含log_log函数的代码中定义main()的源文件(不是标头,而是源文件)之类的扭曲,就无法做您尝试的操作。但是,您真的不想这样做;您真的真的 真的 不想这么做。

让懒惰保护您:输入log_log(CS_POTATOES, "codswallop", -366, "abuse is rampant")log_trace("abuse is rampant")困难得多,因此人们不太可能这样做。而且,您始终可以搜索并替换直接致电log_log的电话,对可能滥用此电话的团队成员提供适当的警告。

答案 1 :(得分:1)

预处理器不了解C。预处理器所做的全部工作是用对log_***的调用替换log_log宏的任何实例。只有在预处理器完成了这些替换之后,编译器才介入读取已被预处理器修改的代码。

编译器不在乎也不知道这些对log_log的调用是由预处理程序进行的。它所看到的只是对您不应该使用的函数的引用,因为您已经声明了static,因此它会发出错误。

答案 2 :(得分:1)

  

为什么宏不能使用静态函数

宏不使用 any 函数。它们只是扩展为源代码或其片段。以这种方式生成的源代码可以包含函数调用,但是它的语义完全相同,就好像它确实出现在文件中一样,而不是来自宏的扩展。

特别是,如果出现在给定文件中的宏扩展为包含函数调用的代码,则被调用函数必须是外部函数,或者其定义必须出现在与调用相同的源文件中。