最近,我在看linux内核源码,看到了一个非常有意思的宏定义,之所以说它有意思是因为我当时看到的时候,给我造成了一定理解误区。今天,先记录下来。
首先,看一个函数,参数列表中有可变参数"...":
cpp
IMG_VOID PVRSRVDebugPrintf (
IMG_UINT32 ui32DebugLevel,
const IMG_CHAR* pszFullFileName,
IMG_UINT32 ui32Line,
const IMG_CHAR* pszFormat,
...
) /**可变参数,至少4个参数,也就是参数个数在4个以上 */
当我追踪这个函数的调用关系的时候,发现使用时使用含参宏:PVR_DPF(x),也就是说定义了一个含参宏PVR_DPF(x)用于替代PVRSRVDebugPrint函数:
cpp
#define PVR_DPF(X) PVRSRVDebugPrintf X
我们查看这个宏PVR_DPF(X)的一个调用关系。
cpp
PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
当时给我造成误区的主要是2个方面:
(1)函数名PVRSRVDebugPrint用于函数调用,后面需要跟着"小括号"但是宏定义的函数名后面没有小括号,那么是如何实现函数调用的呢?
这个相对容易理解,因为宏调用后面跟着2个包含的小括号,因此上面解析后等效于:
cpp
PVRSRVDebugPrintf (PVR_DBG_MESSAGE, "BM_CreateContext")
不太一样的地方就是,函数名后面多了一个"空格",不过也是函数调用。
(2)函数PVRSRVDebugPrintf的参数列表为可变参数,其中固定参数有4个,但是从函数调用看只有2个参数。
2个参数其实是错误的,看起来是2个参数,但是第一个参数也是一个宏,对应宏定义如下:
cpp
#define PVR_DBG_MESSAGE DBGPRIV_MESSAGE,__FILE__, __LINE__
因此函数调用展开后为:
cpp
PVRSRVDebugPrintf (DBGPRIV_MESSAGE,__FILE__, __LINE__, "BM_CreateContext")
因此,函数调用实际是4个参数,而非2个参数。
第二个误区走出的关键是另外一个宏PVR_DBG_MESSAGE实际是3部分组成的。