了解遗留C ++ #define

时间:2012-03-27 12:56:28

标签: c++ legacy

我有一些遗留的C ++代码,我试图更好地理解它。我感到困惑的一个问题是这样的一行:

#define LOG_TRACE_ERROR(s)  LOG_traceError( _T(__FILE__), __LINE__, s )

位于头文件中。我可以看到 LOG_TRACE_ERROR 是代码调用的内容并且它传递了一个字符串,我可以看到 LOG_traceError 是一个实际完成工作的函数,所以我假设这一行是将函数的两个不同名称映射到一起吗?令我困惑的是,为什么参数列表不同(LOG_TRACE_ERROR的字符串和(_T( FILE ), LINE ,s)LOG_traceError)。此外,我无法在任何地方找到 _ FILE _ _ LINE _ s 那么该程序如何知道它们是什么?

4 个答案:

答案 0 :(得分:5)

_FILE_扩展为文件名。

_LINE_扩展为行号。

s是您传递给宏的参数。

当你写:

//file.cpp
//...
LOG_TRACE_ERROR("error here"); //line 13

预处理器会将其转换为:

//file.cpp
//...
LOG_traceError( _T("file.cpp"), "13", "error here" );

_T()是与UNICODE相关的宏。如果在unicode环境中,它会将您的字符串转换为wchar_t*

答案 1 :(得分:3)

__FILE____LINE__是由编译器定义的内部值,它扩展到正在编译的文件和当前行(宏正在扩展为)。

使用宏,当你说(例如):

#define YOUR_MACRO(param1, param2) some_function_here(param1 + param2, 0)

您正在定义一个包含两个参数param1param2的宏(在您的情况下,只有一个参数,其名称为s)。然后,您可以在您认为合适的宏定义中使用这些参数。

注意:在编写宏时要小心,因为它们会变得棘手。在上面的示例中,如果您调用:

YOUR_MACRO(x << 2, y << 2)

它将扩展为:

some_function_here(x << 2 + y << 2, 0);

实际上是:

some_function_here(x << (2 + y) << 2, 0);
肯定不是你的意思!编写好的宏涉及很多括号,并且可能使用编译器的非标准功能来使它们安全。

答案 2 :(得分:2)

__FILE____LINE__以及__DATE____TIME__和其他一些是ISO / IEC 9899:1990(C89)中首先定义的预定义宏)C编程语言的标准,§6.10.8

部分
  

6.10.8预定义的宏名称

     

以下宏名称应由实现定义:

     

__ DATE__预处理翻译单位的翻译日期:一个字符   “Mmm dd yyyy”形式的字符串文字,其中月份的名称相同   那些由asctime生成的   函数,dd的第一个字符是空格字符   值小于10.如果没有翻译日期,则a   应提供实施定义的有效日期。

     

__ FILE__当前源文件的假定名称(字符串文字)。

     

__ LINE__当前源行的假定行号(在当前源文件中)(整数常量)。

     

__ STDC__整数常量1,用于表示符合要求的实现。

     

__ STDC_HOSTED__如果实现是托管实现,则为整数常量1;如果不是,则为整数常量0。

     

__ STDC_VERSION__整数常量199901L。

     

__ TIME__预处理翻译单元的翻译时间:时间形式为“hh:mm:ss”的字符串文字   由asctime函数生成。如果翻译时间不是   可用,应提供实施定义的有效时间。

与所有宏一样,它们在编译代码之前由预处理器进行评估。

答案 3 :(得分:0)

_FILE__LINE_来自您的预处理器。像这样的宏是访问这些值的唯一方法,如果您不希望用户每次调用时都调用_FILE__LINE_,那么您调用Log_traceError(...)的行LOG_traceError(...)。