Quelles sont certaines utilisations de #pragma
en C, avec des exemples?
#pragma
est destiné aux directives du compilateur spécifiques à la machine ou au système d’exploitation, c’est-à-dire qu’il indique au compilateur de faire quelque chose, de définir une option, d’agir, de remplacer certaines valeurs par défaut, etc. pouvant s’appliquer ou non à toutes les machines. et systèmes d'exploitation.
Voir msdn pour plus d'informations.
#pragma
Est utilisé pour faire quelque chose de spécifique à l'implémentation en C, c'est-à-dire être pragmatique pour le contexte actuel plutôt que idéologiquement dogmatique.
Celui que j'utilise régulièrement est #pragma pack(1)
, où j'essaie de tirer davantage de mon espace mémoire sur des solutions intégrées, avec des tableaux de structures qui sinon se retrouveraient avec un alignement de 8 octets.
Dommage que nous n'ayons pas encore de #dogma
. Ce serait amusant ;)
J'essayerais généralement d'éviter l'utilisation de #pragmas si possible, car ils sont extrêmement dépendants du compilateur et non portables. Si vous voulez les utiliser de manière portable, vous devrez entourer chaque pragma avec une paire #if
/#endif
. GCC déconseille l’utilisation de pragmas et ne supporte en réalité que certains d’entre eux pour la compatibilité avec d’autres compilateurs; GCC a d'autres moyens de faire la même chose que d'autres compilateurs utilisent les pragmas.
Par exemple, voici comment vous pouvez vous assurer qu’une structure est compactée (c’est-à-dire qu’il n’ya pas de remplissage entre les membres) dans MSVC:
#pragma pack(Push, 1)
struct PackedStructure
{
char a;
int b;
short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7
Voici comment vous feriez la même chose dans GCC:
struct PackedStructure __attribute__((__packed__))
{
char a;
int b;
short c;
};
// sizeof(PackedStructure == 7)
Le code GCC est plus portable, car si vous voulez le compiler avec un compilateur non-GCC, tout ce que vous avez à faire est de
#define __attribute__(x)
Considérant que si vous voulez porter le code MSVC, vous devez entourer chaque pragma avec une paire #if
/#endif
. Pas beau.
En mettant #pragma once
en haut de votre fichier d’en-tête s’assurera qu’il n’est inclus qu’une fois. Notez que #pragma once
n'est pas standard C99, mais supporté par la plupart des compilateurs modernes.
Une autre solution consiste à utiliser des protecteurs d'inclusion (par exemple, #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */
)
ce que je ressens, c'est #pragma
est une directive dans laquelle, si vous voulez que le code soit spécifique à un emplacement. Vous voulez que le compteur de programme lise à partir de l'adresse spécifique où l'ISR est écrit, vous pouvez spécifier l'ISR à cet emplacement en utilisant #pragma vector=ADC12_VECTOR
et suivi du nom et de la description de Rotine Interrupt
Le meilleur conseil que je puisse vous donner est d'examiner la documentation de votre compilateur, car les pragmas sont par définition spécifiques à l'implémentation. Par exemple, dans des projets intégrés, je les ai utilisés pour localiser le code et les données dans différentes sections ou pour déclarer des gestionnaires d'interruptions. c'est à dire.:
#pragma code BANK1
#pragma data BANK2
#pragma INT3 TimerHandler
#pragma startup
est une directive qui est utilisée pour appeler une fonction avant la fonction principale et pour appeler une autre fonction après la fonction principale, par ex.
#pragma startup func1
#pragma exit func2
Ici, func1
s'exécute avant main
et func2
s'exécute ensuite.
REMARQUE: ce code ne fonctionne que dans le compilateur Turbo-C. Pour obtenir cette fonctionnalité dans GCC, vous pouvez déclarer func1
et func2
comme ça:
void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Il s'agit d'une directive de préprocesseur qui peut être utilisée pour activer ou désactiver certaines fonctionnalités.
Il est de deux types #pragma startup
, #pragma exit
et #pragma warn
.
#pragma startup
nous permet de spécifier des fonctions appelées au démarrage du programme.
#pragma exit
nous permet de spécifier des fonctions appelées à la sortie du programme.
#pragma warn
indique à l'ordinateur de supprimer ou non tout avertissement.
Beaucoup d'autres #pragma
_ styles peuvent être utilisés pour contrôler le compilateur.
Toutes les réponses ci-dessus donnent de bonnes explications pour #pragma
mais je voulais ajouter un petit exemple
Je veux juste expliquer un simple OpenMP example
qui illustrent certaines utilisations de #pragma
faire son travail
OpenMp
briefly
est une implémentation pour la programmation parallèle multi-plateformes à mémoire partagée (alors on peut dire que c'estmachine-specific
ouoperating-system-specific
)
allons à l'exemple
#include <stdio.h>
#include <omp.h>// compile with: /openmp
int main() {
#pragma omp parallel num_threads(4)
{
int i = omp_get_thread_num();
printf_s("Hello from thread %d\n", i);
}
}
la sortie est
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3
Note that the order of output can vary on different machines.
maintenant laissez-moi vous dire ce que #pragma
fait...
il dit au système d'exploitation de lancer le bloc de code sur 4 threads
c'est juste un des many many applications
vous pouvez faire avec le petit #pragma
désolé pour l'échantillon extérieur OpenMP
Résumer, #pragma
indique au compilateur de faire des choses. Voici quelques façons dont je l'utilise:
#pragma
peut être utilisé pour ignorer les avertissements du compilateur. Par exemple, pour que GCC se taise à propos des déclarations de fonction implicites, vous pouvez écrire:
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
Une version plus ancienne de libportable
fait ceci de manière portable .
#pragma once
, lorsqu’il est écrit en haut d’un fichier d’en-tête, le fichier d’en-tête sera inclus une fois. libportable
vérifie pour pragma une fois supporté.