Utilisation de #pragma en C

117

Quelles sont certaines utilisations de #pragmaC, avec des exemples?

MD XF
la source
2
#pragmadirective survit à l'étape de prétraitement. Contrairement à #includeet #define.
smwikipedia
Possible duplication de Que signifie une fois #pragma en C?
@smwikipedia vous voulez dire que certains pragmas survivent? #pragma once est une directive de préprocesseur mais #pragma pack est une directive de compilateur
Lewis Kelsey,

Réponses:

66

#pragma est pour les directives du compilateur qui sont spécifiques à la machine ou au système d'exploitation, c'est-à-dire qu'il dit au compilateur de faire quelque chose, de définir une option, de prendre une action, de remplacer certaines valeurs par défaut, etc. qui peuvent ou non s'appliquer à toutes les machines et à l'exploitation systèmes.

Voir msdn pour plus d'informations.

Steven A. Lowe
la source
11
"qui peut s'appliquer ou non à toutes les machines et systèmes d'exploitation." - et différents compilateurs sur la même machine. Et ce qui pourrait signifier des choses différentes sur différents compilateurs.
Steve Jessop
53

#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 celui #pragma pack(1)où j'essaie de tirer davantage de mon espace mémoire sur des solutions embarquées, avec des tableaux de structures qui, autrement, se retrouveraient avec un alignement de 8 octets.

Dommage que nous n'en ayons pas #dogmaencore. Ce serait amusant ;)

SmacL
la source
@ShaneMacLaughlin, N'améliore-t-il pas pragma(1)réellement la vitesse aussi? Voir stackoverflow.com/questions/3318410/…
Pacerier
4
@Pacerier, généralement pas. Selon les commentaires jalfs, les données alignées sur une limite de 4 octets pour les processeurs 32 bits ou sur une limite de 8 octets pour les processeurs 64 bits seront généralement chargées et stockées en une seule opération. Les données alignées sur des limites plus petites nécessiteront plusieurs opérations pour charger ou stocker. C'est plus lent.
SmacL
35

J'essaierais 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 souhaitez les utiliser de manière portable, vous devrez entourer chaque pragma d'une paire #if/ #endif. GCC déconseille l'utilisation de pragmas, et ne prend en charge que certains d'entre eux pour la compatibilité avec d'autres compilateurs; GCC a d'autres façons de faire les mêmes choses que les autres compilateurs utilisent les pragmas.

Par exemple, voici comment vous assurer qu'une structure est compacte étroitement (c'est-à-dire 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

#define __attribute__(x)

Alors que si vous voulez porter le code MSVC, vous devez entourer chaque pragma d'une paire #if/ #endif. Pas beau.

Adam Rosenfield
la source
3
Donc, si je veux compiler le code GCC sur MSVC et que j'ai besoin de compiler la structure, comment dois-je le faire exactement?
SmacL
2
Pour gcc, c'est struct __attribute__((__packed__)) PackedStructure
Laurent Debricon
#pragma once n'est pas de manière réaliste "dépendant du compilateur et non portable". Il est pris en charge sur toutes les plateformes majeurs et de nombreuses plateformes sans grandes .. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon
1
Notez que C99 et C11 contiennent tous deux des directives (C11) §6.10.6 Pragma et ¶1 Tout pragma de ce type qui n'est pas reconnu par l'implémentation est ignoré. Même C90 dit cela, bien que ce soit dans la section §6.8.6. (Cela rend GCC non conforme s'il s'exécute hacklorsqu'il rencontre un pragma qu'il ne reconnaît pas, comme il le faisait jadis il y a très, très longtemps - voir #pragmaet GCC , etc.)
Jonathan Leffler
15

Mettre #pragma onceen haut de votre fichier d'en-tête garantira qu'il n'est inclus qu'une seule fois. Notez que ce #pragma oncen'est pas le C99 standard, mais pris en charge par la plupart des compilateurs modernes.

Une alternative consiste à utiliser des gardes inclus (par exemple #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)

Schildmeijer
la source
7

ce que je ressens est #pragmaune directive où si vous voulez que le code soit spécifique à l'emplacement. dites une situation où vous voulez que le compteur de programme lise à partir de l'adresse spécifique où l'ISR est écrit, vous pouvez spécifier ISR à cet emplacement en utilisant #pragma vector=ADC12_VECTORet suivi de interrompre le nom des rotines et sa description

sandeep
la source
5

Mon meilleur conseil est de regarder 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 du code et des données dans différentes sections, ou pour déclarer des gestionnaires d'interruption. c'est à dire:

#pragma code BANK1
#pragma data BANK2

#pragma INT3 TimerHandler
Juste amoureux
la source
3
Tous les pragmas sont spécifiques à l'implémentation - à l'exception des pragmas #pragma STDC ..., qui sont standardisés sur toutes les plates-formes (en plus de C99).
Jonathan Leffler
4

Toutes les réponses ci-dessus font de belles explications pour #pragmamais je voulais ajouter un petit exemple

Je veux juste expliquer un simple OpenMP examplequi montre quelques utilisations de #pragmapour faire son travail

OpenMp brieflyest une implémentation pour la programmation parallèle multi-plateforme à mémoire partagée (alors nous pouvons dire que c'est machine-specificou operating-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 #pragmaque ...

il dit au système d'exploitation d'exécuter le bloc de code sur 4 threads

c'est juste l'un de many many applicationsvous peut faire avec le peu#pragma

désolé pour l'échantillon extérieur OpenMP

Basheer AL-MOMANI
la source
3

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 exitet #pragma warn.

#pragma startup nous permet de spécifier les fonctions appelées au démarrage du programme.

#pragma exit nous permet de spécifier les fonctions appelées à la sortie du programme.

#pragma warn indique à l'ordinateur de supprimer ou non tout avertissement.

De nombreux autres #pragmastyles peuvent être utilisés pour contrôler le compilateur.

suresh pareek
la source
3

#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 exemple

#pragma startup func1
#pragma exit func2

Ici, func1s'exécute avant mainet func2s'exécute après.

REMARQUE: ce code fonctionne uniquement dans le compilateur Turbo-C. Pour réaliser cette fonctionnalité dans GCC, vous pouvez déclarer func1et func2aimer ceci:

void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Sparkzz
la source
2

Pour résumer, #pragmadit au compilateur de faire des choses. Voici quelques façons dont je l'utilise:

  • #pragmapeut être utilisé pour ignorer les avertissements du compilateur. Par exemple, pour faire taire GCC des déclarations de fonctions implicites, vous pouvez écrire:

    #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"

    Une ancienne version de le libportablefait de manière portable .

  • #pragma once, lorsqu'il est écrit en haut d'un fichier d'en-tête, ce fichier d'en-tête sera inclus une fois. libportable vérifie le support pragma une fois.

MD XF
la source