Pragma-direktiv och nyckelorden __pragma
och _Pragma
Pragma-direktiv anger maskinspecifika eller operativsystemspecifika kompilatorfunktioner. En rad som börjar med #pragma
anger ett pragma direktiv. Med det Microsoft-specifika nyckelordet __pragma
kan du koda pragma direktiv i makrodefinitioner. Standardoperatorn _Pragma
preprocessor, som introducerades i C99 och antogs av C++11, är liknande.
Syntax
#pragma
tokensträng
__pragma(
tokensträng)
// två inledande understreck – Microsoft-specifikt tillägg
_Pragma(
strängliteral)
// C99
Anmärkningar
Varje implementering av C och C++ stöder vissa funktioner som är unika för värddatorn eller operativsystemet. Vissa program måste till exempel utöva exakt kontroll över platsen för data i minnet eller styra hur vissa funktioner tar emot parametrar. De #pragma
direktiven erbjuder ett sätt för varje kompilator att erbjuda maskin- och operativsystemspecifika funktioner, samtidigt som den övergripande kompatibiliteten med C- och C++-språken upprätthålls.
Pragma-direktiv är datorspecifika eller operativsystemspecifika per definition och skiljer sig vanligtvis åt för varje kompilator. En pragma kan användas i ett villkorligt direktiv för att tillhandahålla nya funktioner för förprocessorer. Du kan också använda en för att tillhandahålla implementeringsdefinierad information till kompilatorn.
Den tokensträngen är en serie tecken som representerar en specifik kompilatorinstruktion och eventuella argument. Taltecknet (#
) måste vara det första icke-blankstegstecknet på raden som innehåller pragma. Blankstegstecken kan avgränsa taltecknet och ordet "pragma". Efter #pragma
skriver du all text som översättaren kan parsa som förbearbetningstoken. Argumentet för att #pragma
är föremål för makroexpansion.
strängliteral är indata till _Pragma
. Yttre citattecken och inledande/avslutande blanksteg tas bort.
\"
ersätts med "
och \\
ersätts med \
.
Kompilatorn utfärdar en varning när den hittar en pragma som den inte känner igen och fortsätter kompilering.
Microsoft C- och C++-kompilatorerna känner igen följande pragma direktiv:
alloc_text
auto_inline
bss_seg
check_stack
code_seg
comment
component
conform
1
const_seg
data_seg
deprecated
1 stöds endast av C++-kompilatorn.
Pragma-direktiv och kompilatoralternativ
Vissa pragma-direktiv har samma funktioner som kompilatoralternativ. När en pragma nås i källkoden åsidosätter den det beteende som anges av kompilatoralternativet. Om du till exempel har angett /Zp8
kan du åsidosätta den här kompilatorinställningen för specifika delar av koden med 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
// ...
Nyckelordet __pragma
Kompilatorn stöder också det Microsoft-specifika nyckelordet __pragma
, som har samma funktioner som #pragma
-direktivet. Skillnaden är att nyckelordet __pragma
kan användas infogat i en makrodefinition.
#pragma
-direktivet kan inte användas i en makrodefinition, eftersom kompilatorn tolkar talteckentecknet ('#') i direktivet som strängoperator (#).
I följande kodexempel visas hur nyckelordet __pragma
kan användas i ett makro. Den här koden är utdragen från mfcdual.h-rubriken i ACDUAL-exemplet i "Kompilator COM-supportexempel":
#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; \
Operatorn _Pragma
förbearbetning
_Pragma
liknar det Microsoft-specifika nyckelordet __pragma
. Den introducerades i C-standarden i C99 och C++-standarden i C++11. Den är endast tillgänglig i C när du anger alternativet /std:c11
eller /std:c17
. För C++är den tillgänglig i alla /std
lägen, inklusive standardläget.
Till skillnad från #pragma
kan du _Pragma
placera pragma-direktiv i en makrodefinition. Strängliteralen bör vara det som du annars skulle lägga till efter en #pragma
-instruktion. Till exempel:
#pragma message("the #pragma way")
_Pragma ("message( \"the _Pragma way\")")
Citattecken och snedstreck bör vara undantagna, som du ser ovan. En pragma sträng som inte känns igen ignoreras.
Följande kodexempel visar hur nyckelordet _Pragma
kan användas i ett assert-liknande makro. Det skapar ett pragma direktiv som undertrycker en varning när villkorsuttrycket råkar vara konstant.
Makrodefinitionen använder do ... while(0)
idiom för makron med flera instruktioner så att det kan användas som om det vore en instruktion. Mer information finns i C-makro med flera rader på Stack Overflow. Instruktionen _Pragma
i exemplet gäller bara för den kodrad som följer den.
// 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;
}