条件包含和条件函数签名修改
为了有条件地包含一个代码块,预处理器有几个指令(例如 #if
,#ifdef
,#else
,#endif
等)。
/* Defines a conditional `printf` macro, which only prints if `DEBUG`
* has been defined
*/
#ifdef DEBUG
#define DLOG(x) (printf(x))
#else
#define DLOG(x)
#endif
普通 C 关系运算符可用于 #if
条件
#if __STDC_VERSION__ >= 201112L
/* Do stuff for C11 or higher */
#elif __STDC_VERSION__ >= 199901L
/* Do stuff for C99 */
#else
/* Do stuff for pre C99 */
#endif
#if
指令的行为类似于 C if
语句,它只包含整数常量表达式,并且不包含强制转换。它支持一个额外的一元运算符 defined( identifier )
,如果定义了标识符则返回 1
,否则返回 0
。
#if defined(DEBUG) && !defined(QUIET)
#define DLOG(x) (printf(x))
#else
#define DLOG(x)
#endif
条件函数签名修改
在大多数情况下,应用程序的发布版本应该具有尽可能少的开销。但是,在测试临时构建期间,其他日志和有关问题的信息可能会有所帮助。
例如,假设有一些函数 SHORT SerOpPluAllRead(PLUIF *pPif, USHORT usLockHnd)
,在进行测试构建时,需要生成关于其使用的日志。但是,此功能在多个地方使用,并且希望在生成日志时,部分信息是知道调用函数的位置。
因此,使用条件编译,你可以在包含文件声明函数中使用以下内容。这将使用函数的调试版本替换函数的标准版本。预处理器用于替换函数 SerOpPluAllRead()
的调用,调用函数 SerOpPluAllRead_Debug()
,带有两个附加参数,文件名和函数使用位置的行号。
条件编译用于选择是否使用调试版本覆盖标准函数。
#if 0
// function declaration and prototype for our debug version of the function.
SHORT SerOpPluAllRead_Debug(PLUIF *pPif, USHORT usLockHnd, char *aszFilePath, int nLineNo);
// macro definition to replace function call using old name with debug function with additional arguments.
#define SerOpPluAllRead(pPif,usLock) SerOpPluAllRead_Debug(pPif,usLock,__FILE__,__LINE__)
#else
// standard function declaration that is normally used with builds.
SHORT SerOpPluAllRead(PLUIF *pPif, USHORT usLockHnd);
#endif
这允许你使用一个版本覆盖函数 SerOpPluAllRead()
的标准版本,该版本将在调用函数的文件中提供文件名和行号。
有一个重要的考虑因素: 使用此函数的任何文件都必须包含使用此方法的头文件,以便预处理器修改函数。否则,你将看到链接器错误。
函数的定义如下所示。此源的作用是请求预处理器将函数 SerOpPluAllRead()
重命名为 SerOpPluAllRead_Debug()
并修改参数列表以包含两个附加参数,指向调用函数的文件名称的指针以及文件中的行号使用该功能。
#if defined(SerOpPluAllRead)
// forward declare the replacement function which we will call once we create our log.
SHORT SerOpPluAllRead_Special(PLUIF *pPif, USHORT usLockHnd);
SHORT SerOpPluAllRead_Debug(PLUIF *pPif, USHORT usLockHnd, char *aszFilePath, int nLineNo)
{
int iLen = 0;
char xBuffer[256];
// only print the last 30 characters of the file name to shorten the logs.
iLen = strlen (aszFilePath);
if (iLen > 30) {
iLen = iLen - 30;
}
else {
iLen = 0;
}
sprintf (xBuffer, "SerOpPluAllRead_Debug(): husHandle = %d, File %s, lineno = %d", pPif->husHandle, aszFilePath + iLen, nLineNo);
IssueDebugLog(xBuffer);
// now that we have issued the log, continue with standard processing.
return SerOpPluAllRead_Special(pPif, usLockHnd);
}
// our special replacement function name for when we are generating logs.
SHORT SerOpPluAllRead_Special(PLUIF *pPif, USHORT usLockHnd)
#else
// standard, normal function name (signature) that is replaced with our debug version.
SHORT SerOpPluAllRead(PLUIF *pPif, USHORT usLockHnd)
#endif
{
if (STUB_SELF == SstReadAsMaster()) {
return OpPluAllRead(pPif, usLockHnd);
}
return OP_NOT_MASTER;
}