@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.
"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 ;)
@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:
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 */)
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
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
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: /openmpint 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 0Hello from thread 1Hello from thread 2Hello from thread 3Note 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
#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:
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 once, lorsqu'il est écrit en haut d'un fichier d'en-tête, ce fichier d'en-tête sera inclus une fois. libportablevérifie le support pragma une fois.
#pragma
directive survit à l'étape de prétraitement. Contrairement à#include
et#define
.Réponses:
#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.
la source
#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
#dogma
encore. Ce serait amusant ;)la source
pragma(1)
réellement la vitesse aussi? Voir stackoverflow.com/questions/3318410/…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:
Voici comment vous feriez la même chose dans GCC:
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.la source
struct __attribute__((__packed__)) PackedStructure
hack
lorsqu'il rencontre un pragma qu'il ne reconnaît pas, comme il le faisait jadis il y a très, très longtemps - voir#pragma
et GCC , etc.)Mettre
#pragma once
en haut de votre fichier d'en-tête garantira qu'il n'est inclus qu'une seule fois. Notez que ce#pragma once
n'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 */
)la source
ce que je ressens est
#pragma
une 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_VECTOR
et suivi de interrompre le nom des rotines et sa descriptionla source
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:
la source
Toutes les réponses ci-dessus font de belles explications pour
#pragma
mais je voulais ajouter un petit exempleJe veux juste expliquer un
simple OpenMP example
qui montre quelques utilisations de#pragma
pour faire son travailallons à l'exemple
la sortie est
maintenant laissez-moi vous dire ce
#pragma
que ...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 applications
vous peut faire avec le peu#pragma
désolé pour l'échantillon extérieur
OpenMP
la source
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 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
#pragma
styles peuvent être utilisés pour contrôler le compilateur.la source
#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 exempleIci,
func1
s'exécute avantmain
etfunc2
s'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
func1
etfunc2
aimer ceci:la source
Pour résumer,
#pragma
dit 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 faire taire GCC des déclarations de fonctions implicites, vous pouvez écrire:Une ancienne version de le
libportable
fait 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.la source