使用 C 预处理器指令进行编译时检查
Posted
技术标签:
【中文标题】使用 C 预处理器指令进行编译时检查【英文标题】:Compile time check with C preprocessor directives 【发布时间】:2012-08-31 21:57:13 【问题描述】:有没有办法在编译时对我的LOGGING
-macro(如下所示)进行日志级别检查?应该是可能的,因为在编译期间已经知道条件(如果(pLogLevel
LOGGING(LOG_DEBUG, "FALSE - Wrong Marker\n");
最初我认为#define
中的#if
directives 可以帮助我,但this 文章告诉我这是不可能的。这是我的问题的源代码:
#ifndef __LOGGING_H__
#define __LOGGING_H__ 1
#include <time.h>
#define LOG_EMERG 0
#define LOG_ALERT 1
#define LOG_CRIT 2
#define LOG_ERROR 3
#define LOG_WARN 4
#define LOG_NOTICE 5
#define LOG_INFO 6
#define LOG_DEBUG 7
#define LOG_NONE 8
/* set the global logging level here */
#define LOG_LEVEL LOG_INFO
void print_timestamp(void);
#if LOG_LEVEL == LOG_DEBUG
#define _LOG_PREAMBLE \
fprintf(stdout, "%s:%d ", __FILE__, __LINE__);
#else
#define _LOG_PREAMBLE \
print_timestamp();
#endif
#if LOG_LEVEL == LOG_EMERG
#define _LOG_LEVEL fprintf(stdout, "EMERG ");
#elif LOG_LEVEL == LOG_ALERT
#define _LOG_LEVEL fprintf(stdout, "ALERT ");
#elif LOG_LEVEL == LOG_CRIT
#define _LOG_LEVEL fprintf(stdout, "CRIT ");
#elif LOG_LEVEL == LOG_ERROR
#define _LOG_LEVEL fprintf(stdout, "ERROR ");
#elif LOG_LEVEL == LOG_WARN
#define _LOG_LEVEL fprintf(stdout, "WARN ");
#elif LOG_LEVEL == LOG_NOTICE
#define _LOG_LEVEL fprintf(stdout, "NOTICE ");
#elif LOG_LEVEL == LOG_INFO
#define _LOG_LEVEL fprintf(stdout, "INFO ");
#elif LOG_LEVEL == LOG_INFO
#define _LOG_LEVEL fprintf(stdout, "DEBUG ");
#else
#define _LOG_LEVEL
#endif
#define LOGGING(pLogLevel, ...) \
/* change this to compile time conditional if possible */ \
if (pLogLevel <= LOG_LEVEL) \
\
_LOG_PREAMBLE \
_LOG_LEVEL \
fprintf(stdout, ##__VA_ARGS__); \
#endif /* __LOGGING_H__ */
【问题讨论】:
很有可能,当您打开优化时,编译器会在条件为假时消除您的 LOGGING() 宏的代码,并且在条件为时消除 if() 条件检查true - 在代码中只留下 if() 的主体。如果没有,我会将其作为错误提交给编译器。 这是代码生成器的工作。可以看到 if() 语句总是假的,知道消除代码。您无需提供帮助,只需确保启用了优化器即可。 谢谢你们两个。这些是有用的 cmets。编译器或优化器在始终为真或假的条件中启用/禁用代码绝对是有意义的。 【参考方案1】:一种方法是将日志级别合并到日志宏中。
这将创建一组宏,这些宏将根据日志级别打开或关闭。
您将使用这些宏,它们是否出现取决于编译时的日志级别。所以他们会像下面这样使用。
LOGGING_LEVEL_DEBUG("a Debug log.");
//.... some code
LOGGING_LEVEL_EMERG("a Emerge log.");
因此宏定义如下所示:
#define LOG_EMERG 0
#define LOG_ALERT 1
#define LOG_CRIT 2
#define LOG_ERROR 3
#define LOG_WARN 4
#define LOG_NOTICE 5
#define LOG_INFO 6
#define LOG_DEBUG 7
#define LOG_NONE 8
/* set the global logging level here */
#define LOG_LEVEL LOG_INFO
void print_timestamp(void);
#if LOG_LEVEL >= LOG_DEBUG
#define _LOG_PREAMBLE \
fprintf(stdout, "%s:%d ", __FILE__, __LINE__);
#else
#define _LOG_PREAMBLE \
print_timestamp();
#endif
#if LOG_LEVEL >= LOG_EMERG
#define LOGGING_LEVEL_EMERG(...) \
\
_LOG_PREAMBLE \
fprintf(stdout, "EMERG "); \
fprintf(stdout, ##__VA_ARGS__); \
#else
#define LOGGING_LEVEL_EMERG(...)
#endif
#if LOG_LEVEL >= LOG_ALERT
#define LOGGING_LEVEL_ALERT(...) \
\
_LOG_PREAMBLE \
fprintf(stdout, "ALERT "); \
fprintf(stdout, ##__VA_ARGS__); \
#else
#define LOGGING_LEVEL_ALERT(...)
#endif
【讨论】:
【参考方案2】:您可以有条件地自己定义宏:
#if LOG_LEVEL > 0
# define LOG(...) printf(__VA_ARGS__)
#else
# define LOG(...)
#endif
#if LOG_LEVEL > 1
// and so forth
【讨论】:
以上是关于使用 C 预处理器指令进行编译时检查的主要内容,如果未能解决你的问题,请参考以下文章