C Language Inclusión condicional y modificación de la firma de la función condicional.


Ejemplo

Para incluir condicionalmente un bloque de código, el preprocesador tiene varias directivas (por ejemplo #if , #ifdef , #else , #endif , etc).

/* 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

Se pueden usar operadores relacionales C normales para la condición #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

Las directivas #if comportan de manera similar a la instrucción C if , solo contendrá expresiones constantes integrales y no emitirá. Admite un operador unario adicional, defined( identifier ) , que devuelve 1 si el identificador está definido, y 0 contrario.

#if defined(DEBUG) && !defined(QUIET)
#define DLOG(x) (printf(x))
#else
#define DLOG(x)
#endif

Modificación de la firma de la función condicional

En la mayoría de los casos, se espera que la versión de lanzamiento de una aplicación tenga la menor sobrecarga posible. Sin embargo, durante la prueba de una compilación provisional, pueden ser útiles los registros adicionales y la información sobre los problemas encontrados.

Por ejemplo, supongamos que hay alguna función SHORT SerOpPluAllRead(PLUIF *pPif, USHORT usLockHnd) que al realizar una compilación de prueba se generará un registro sobre su uso. Sin embargo, esta función se usa en múltiples lugares y se desea que al generar el registro, parte de la información sea para saber de dónde se llama la función.

Entonces, al usar la compilación condicional, puede tener algo como lo siguiente en el archivo de inclusión que declara la función. Esto reemplaza la versión estándar de la función con una versión de depuración de la función. El preprocesador se usa para reemplazar las llamadas a la función SerOpPluAllRead() con llamadas a la función SerOpPluAllRead_Debug() con dos argumentos adicionales, el nombre del archivo y el número de línea donde se usa la función.

La compilación condicional se utiliza para elegir si se reemplaza o no la función estándar con una versión de depuración.

#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

Esto le permite anular la versión estándar de la función SerOpPluAllRead() con una versión que proporcionará el nombre del archivo y el número de línea en el archivo donde se llama la función.

Hay una consideración importante: cualquier archivo que use esta función debe incluir el archivo de encabezado donde se utiliza este método para que el preprocesador modifique la función. De lo contrario verá un error de vinculador.

La definición de la función sería similar a la siguiente. Lo que hace esta fuente es solicitar que el preprocesador cambie el nombre de la función SerOpPluAllRead() para que sea SerOpPluAllRead_Debug() y para modificar la lista de argumentos para incluir dos argumentos adicionales, un puntero al nombre del archivo donde se llamó la función y el número de línea. en el archivo en el que se utiliza la función.

#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;
}