Directivas pragma y las palabras clave __pragma y _Pragma

Las directivas Pragma especifican características del compilador específicas de la máquina o del sistema operativo. Una línea que comienza por #pragma especifica una directiva pragma. La palabra clave __pragma, que es específica del compilador de Microsoft, permite la programación de directivas pragma dentro de definiciones de macro. El operador de preprocesador estándar _Pragma, introducido en C99 y adoptado por C++11, es similar.

Sintaxis

#pragmatoken-string
__pragma(token-string) // dos caracteres de subrayado iniciales: extensión específica de Microsoft
_Pragma(string-literal) // C99

Comentarios

Cada implementación de C y C++ admite algunas características exclusivas del equipo host o del sistema operativo. Algunos programas, por ejemplo, deben realizar el control preciso sobre la ubicación de los datos en la memoria o controlar la manera en que determinadas funciones reciben los parámetros. Las directivas #pragma proporcionan un método para que cada compilador ofrezca características específicas del equipo o del sistema operativo a la vez que mantienen la compatibilidad total con los lenguajes C y C++.

La s directivas pragma son específicas de la máquina o del sistema operativo específico por definición, y normalmente son diferentes para cada compilador. Una directiva pragma se puede usar en una directiva condicional para proporcionar una nueva funcionalidad de preprocesador. O bien, use uno para proporcionar información definida por la implementación al compilador.

token-ring es una serie de caracteres que proporcionan instrucciones del compilador y argumentos concretos, si los hay. El signo de número (#) debe ser el primer carácter que no sea un carácter de espacio en blanco de la línea que contiene la directiva pragma. Los caracteres de espacio en blanco pueden separar el signo de número y la palabra "pragma". A continuación de #pragma, se ha de escribir el texto que el traductor pueda analizar como tokens de preprocesamiento. El argumento para #pragma está sujeto a la expansión de macro.

string-literal es la entrada en _Pragma. Se quitan las comillas externas y los espacios en blanco iniciales o finales. \" se reemplaza por " y \\ se reemplaza por \.

El compilador emite una advertencia cuando encuentra un pragma que no reconoce y continúa la compilación.

Los compiladores de Microsoft C y C++ reconocen las directivas pragma siguientes:

1 Solo la admite el compilador de C++.

Directivas pragma y opciones del compilador

Algunas directivas pragma proporcionan la misma funcionalidad que las opciones del compilador. Cuando una directiva pragma se encuentra en el código fuente, invalida el comportamiento especificado por la opción del compilador. Por ejemplo, si se ha especificado /Zp8, se puede reemplazar esta configuración del compilador para secciones específicas del código con pack:

cl /Zp8 some_file.cpp
// some_file.cpp - packing is 8
// ...
#pragma pack(push, 1) - packing is now 1
// ...
#pragma pack(pop) - packing is 8 again
// ...

La palabra clave __pragma.

El compilador también admite la palabra clave __pragma, específica de Microsoft, que tiene la misma funcionalidad que la directiva #pragma. La diferencia es que la palabra clave __pragma se puede usar insertada en una definición de macro. La directiva #pragma no se puede utilizar en una definición de macro porque el compilador interpreta el carácter de signo de número ("#") en la directiva como operador de generación de cadenas (#).

En el siguiente ejemplo de código se muestra cómo se puede utilizar la palabra clave __pragma en una macro. Este código se ha extraído del encabezado mfcdual.h del ejemplo ACDUAL en "Ejemplos de compatibilidad COM del compilador":

#define CATCH_ALL_DUAL \
CATCH(COleException, e) \
{ \
_hr = e->m_sc; \
} \
AND_CATCH_ALL(e) \
{ \
__pragma(warning(push)) \
__pragma(warning(disable:6246)) /*disable _ctlState prefast warning*/ \
AFX_MANAGE_STATE(pThis->m_pModuleState); \
__pragma(warning(pop)) \
_hr = DualHandleException(_riidSource, e); \
} \
END_CATCH_ALL \
return _hr; \

Operador _Pragma de preprocesamiento

_Pragma es similar a la palabra clave __pragma específica de Microsoft. Se introdujo en el estándar de C en C99 y el estándar de C++ en C++11. Solo está disponible en C cuando se especifica la opción /std:c11 o /std:c17. Para C++, está disponible en todos los modos /std, incluido el valor predeterminado.

A diferencia de #pragma, _Pragma permite colocar directivas pragma en una definición de macro. El literal de la cadena debe ser el que se pondría después de una instrucción #pragma. Por ejemplo:

#pragma message("the #pragma way")
_Pragma ("message( \"the _Pragma way\")") 

Las comillas y barras diagonales inversas deben ser de escape, como se muestra anteriormente. Se omite una cadena pragma que no se reconoce.

En el siguiente ejemplo de código se muestra cómo se puede utilizar la palabra clave _Pragma en una macro similar a assert. Crea una directiva pragma que suprime una advertencia cuando la expresión de condición se produce como constante.

La definición de macro usa la expresión do ... while(0) para las macros de varias instrucciones para que se pueda usar como si fuera una instrucción. Para más información, consulte Macro de varias líneas de C en Stack Overflow. La instrucción _Pragma del ejemplo solo se aplica a la línea de código que la sigue.

// Compile with /W4

#include <stdio.h>
#include <stdlib.h>

#define MY_ASSERT(BOOL_EXPRESSION) \
    do { \
        _Pragma("warning(suppress: 4127)") /* C4127 conditional expression is constant */  \
        if (!(BOOL_EXPRESSION)) {   \
            printf("MY_ASSERT FAILED: \"" #BOOL_EXPRESSION "\" on %s(%d)", __FILE__, __LINE__); \
            exit(-1); \
        } \
    } while (0)

int main()
{
    MY_ASSERT(0 && "Note that there is no warning: C4127 conditional expression is constant");

    return 0;
}

Consulte también

Referencia del preprocesador de C/C++
Directivas de Cpragma
Palabras clave