條件包含和條件函式簽名修改

為了有條件地包含一個程式碼塊,前處理器有幾個指令(例如 #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;
}