我有一些遗留的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 那么该程序如何知道它们是什么?
答案 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)
您正在定义一个包含两个参数param1
和param2
的宏(在您的情况下,只有一个参数,其名称为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(...)。