Utilisation de #pragma sous Linux

Utilisation de la directive précompilée #pragma

Original: https://blog.csdn.net/tigerjibo/article/details/7000861 

En examinant récemment le code d'un projet open source, j'ai trouvé que les programmes #pragma sont utilisés dans de nombreux endroits. Par conséquent, j'ai demandé à l'enseignant de Google et résumé l'utilisation courante des instructions précompilées #pragma. Je vais maintenant partager avec vous.

1. #pragma la méthode la plus couramment utilisée

1. #progma pack (n)

1> fonction:

Utilisez la directive de précompilation #progma pack pour modifier la valeur par défaut du compilateur (pas absolue, certains compilateurs ne peuvent utiliser qu'un alignement de données fixe).

2> Description

Dans la plupart des cas, nous ne considérons pas les problèmes d'alignement lorsque nous écrivons des programmes, car le compilateur choisira la bonne stratégie pour nous. La plupart des compilateurs utilisent l'alignement sur quatre octets par défaut.

Vous pouvez voir un programme pour comprendre:

Procédure A:

#include <stdio.h>

struct A

{

    int a;

    char b;

    court c;   

};

int  main()

{

    int d;

    d = sizeof (structure A);

    printf ("theleng =% d \ n", d);

     return 0;

}

Noter:

(1) En général, nous utilisons des processeurs 32 bits et le numéro d'octet d'alignement par défaut du compilateur vc est de 4 octets. Sous gcc, par défaut, le plus grand type de variable de la structure est aligné sur les octets.

La structure A contient un entier d'une longueur de 4 octets, un caractère d'une longueur de 1 octet et une donnée courte d'une longueur de 2 octets. L'espace utilisé par A doit donc être de 7 octets. Mais parce que le compilateur doit aligner les membres de données dans l'espace. Utilisez donc la valeur sizeof (strcut A) de 8 "a occupe 4 octets, b occupe un octet et c occupe deux octets, de sorte que le compilateur mettra b et C dans un 4 octets, donc la structure Body A occupe 8 octets"

(2) Nous discutons maintenant des avantages de l'alignement d'octets:

L'espace mémoire des ordinateurs modernes est divisé en octets. En théorie, il semble que l'accès à n'importe quel type de variable puisse commencer à partir de n'importe quelle adresse, mais la situation réelle est que lors de l'accès à une variable spécifique, elle est souvent accédée à une mémoire spécifique adresse. Tous les types de données doivent être disposés dans l'espace selon certaines règles, au lieu d'être disposés les uns après les autres dans l'ordre, c'est l'alignement

 

Le rôle et la raison de l'alignement: Le traitement de l'espace de stockage par différentes plates-formes matérielles est très différent. Certaines plates-formes ne peuvent accéder à certains types de données qu'à partir de certaines adresses spécifiques. D'autres plates-formes peuvent ne pas avoir cette situation, mais le plus courant est que si le stockage des données n'est pas aligné selon les exigences de la plate-forme, cela entraînera une perte d'efficacité d'accès.

 

Par exemple, certaines plates-formes commencent avec une adresse paire à chaque fois. Si un type int (en supposant un système 32 bits) est stocké au début de l'adresse paire, alors un cycle de lecture peut être lu, et s'il est stocké au adresse impaire, à certains endroits, cela peut prendre 2 cycles de lecture et reconstituer les octets haut et bas des deux résultats de lecture pour obtenir les données int. De toute évidence, l'efficacité de la lecture a beaucoup baissé. C'est aussi un jeu entre l'espace et le temps

3> Comment utiliser?

Exemples d'utilisation:
#pragma pack (push) // Enregistrer l'état d'alignement précédent, push consiste à pousser l'état d'alignement précédent sur la pile  
#pragma pack (1) // Spécifier le nouvel état d'alignement, 1 octet
// vous définir Le structure de  
// …………  
#pragma pack (pop) // Pop la pile et restaure l'état d'alignement précédent

Maintenant, nous modifions le programme tout à l'heure:

Procédure B:

#include <stdio.h>

 

#pragma pack (push)

pack #pragma (1)

 

struct A

{

    int a;

    char b;

    court c;   

};

#pragma pack (pop);

int  main()

{

    int d;

    d = sizeof (structure A);

    printf ("theleng =% d \ n", d);

     return 0;

}

À ce moment, parce qu'elle est alignée d'un octet, la structure A occupe un total de 7 octets.

2. #pragma message ("string constant")

1> fonction:

Lorsque le compilateur rencontre cette instruction, il imprime le texte du message dans la fenêtre de sortie de compilation

2> Description:

Lorsque nous définissons de nombreuses macros dans le programme pour contrôler la version du code source, nous pouvons oublier si nous avons correctement défini ces macros. À ce stade, nous pouvons utiliser cette instruction pour vérifier lors de la compilation.

3> Comment utiliser?
#pragma message ("macro activée!")

Remarque: il n'y a pas de point-virgule après message () ici.

3. # pragma une fois

1> fonction:

Ajoutez simplement cette instruction au tout début du fichier d'en-tête pour vous assurer que le fichier d'en-tête est compilé une fois

2> Remarque: la différence entre #pragma once et #ifndef

(1) Similitudes:

Afin d'éviter que le même fichier ne soit inclus plusieurs fois, il n'y a pas beaucoup de différence entre le mode #ifndef et le mode #pragma once (à condition que le compilateur puisse prendre en charge les deux modes en même temps).

(2) Comment utiliser les deux:

première méthode:

#ifndef __TIGER_H__

#define __TIGER_H__

……… .// Quelques déclarations

#fin si

Deuxième méthode:

#pragma une fois

……… // Quelques déclarations de déclaration

(3) La différence entre les deux:

La méthode #ifndef repose sur le fait que les noms de macro ne peuvent pas entrer en conflit. Cela garantit non seulement que le même fichier ne sera pas inclus plusieurs fois, mais également que deux fichiers d'en-tête avec le même contenu ne seront pas inclus accidentellement en même temps. . Bien sûr, l'inconvénient est que si les noms de macro de différents fichiers d'en-tête "plantent" accidentellement, cela peut provoquer l'existence des fichiers d'en-tête, mais le compilateur insiste sur le fait que la déclaration est introuvable.

#pragma once est garanti par le compilateur: le même fichier ne sera pas inclus plusieurs fois. Notez que le même fichier mentionné ici fait référence à un fichier physique et non à deux fichiers avec le même contenu. L'avantage est que vous n'avez plus à penser à un nom de macro, et bien sûr, il n'y aura pas de problèmes étranges causés par des collisions de noms de macro. L'inconvénient correspondant est que s'il existe plusieurs copies d'un fichier d'en-tête, cette méthode ne peut garantir qu'elles ne seront pas incluses à plusieurs reprises. Bien sûr, comparé au problème de "déclaration introuvable" causé par des collisions de noms de macro, les inclusions répétées sont plus faciles à trouver et à corriger.

Pour #pragmaonce, selon MSDN, cela peut empêcher un fichier d'être inclus plusieurs fois. Par rapport à la protection de fichier sous la forme #ifndef #define #endif, la première dépend de la plate-forme et a une faible portabilité, mais elle est plus efficace car elle n'a pas besoin d'ouvrir le fichier inclus pour déterminer si le fichier a été contenu. Bien sûr, ce travail est fait pour nous par le système. L'avantage de ce dernier est qu'il s'agit d'une fonctionnalité liée à la langue, donc la portabilité est bonne. Mais lors de l'inclusion d'un fichier, ouvrez uniquement le fichier et évaluez si le fichier a été inclus selon que la macro de protection du fichier a été définie. L'efficacité est relativement faible. Bien entendu, lorsque #include, le programmeur peut également juger si la macro de protection du fichier à inclure a été définie, pour décider d'inclure ou non le fichier. Similaire au code suivant:

#ifndef FILE_H_

#Incluez "file.h"

#fin si

Cela peut améliorer l'efficacité et garantir la portabilité. Cependant, la dépendance entre les fichiers est élevée. Si la macro de protection d'un fichier est modifiée, tous les fichiers contenant ce fichier au format ci-dessus doivent être modifiés. Contrairement à l'idée de modularité.

2. #pragma quelques autres méthodes

1. Le paramètre #pragma est code_seg.

1> Format: 

#pragma code_seg ([[{push | pop},] [identifiant,]] ["segment-name" [, "segment-class"])

2> Fonction:

Il peut définir le segment de code du code de fonction dans le programme, qui sera utilisé lorsque nous développerons le pilote

3> Description:

Cette instruction est utilisée pour spécifier la section où la fonction est stockée dans le fichier .obj. Pour observer le fichier OBJ, vous pouvez utiliser le programme de ligne de commande dumpbin fourni avec VC. La section de stockage par défaut de la fonction dans le fichier .obj est la section .text, si code_seg ne prend pas de paramètres., La fonction est stockée dans la section .text. push (paramètre optionnel) Placez un enregistrement sur la pile du compilateur interne. Le paramètre optionnel peut être un identifiant ou un nom de section. pop (paramètre facultatif) Pop un enregistrement du haut de la pile. L'enregistrement peut être un identificateur ou un nom de section. identifiant (paramètre optionnel) Lorsque l'instruction push est utilisée, un identifiant est attribué à l'enregistrement poussé dans la pile. Lorsque l'identifiant est supprimé, l'enregistrement dans la pile qui lui est associé sera extrait de la pile. "segment-name" (paramètre optionnel) représente le nom de la section où la fonction est stockée

3> Exemple:

// Par défaut, les fonctions sont stockées dans la section .text

void func1 () {// stocké dans .text

}

 

// Stocke la fonction dans la section .my_data1

#pragma code_seg (". my_data1")

void func2 () {// stocké dans my_data1

}

 

// r1 est l'identifiant, placez la fonction dans la section .my_data2

#pragma code_seg (push, r1, ".my_data2")

void func3 () {// stocké dans my_data2

}

 

int main() {

}

2. # pragma hdrstop

1> fonction:

Indique que le fichier d'en-tête pré-compilé se termine ici, les fichiers d'en-tête suivants ne sont pas précompilés, BCB peut précompiler les fichiers d'en-tête pour accélérer le lien, mais si tous les fichiers d'en-tête sont précompilés, cela peut prendre trop de temps beaucoup d'espace disque, utilisez donc cette option pour exclure certains fichiers d'en-tête. 

Parfois, il y a des dépendances entre les unités, par exemple, l'unité A dépend de l'unité B, donc l'unité B doit être compilée avant l'unité A. Vous pouvez utiliser #pragma startup pour spécifier la priorité de compilation. Si le package #pragma (smart_init) est utilisé, BCB sera compilé en fonction de la priorité. 
3. Avertissement #pragma

1> fonction:

Cette directive permet de modifier sélectivement le comportement des messages d'avertissement du compilateur

2> Format de commande:

#pragma warning (warning-specifier: warning-number-list [; warning-specifier: warning-number-list ...]

#pragma avertissement (appuyez sur [, n])

#pragma avertissement (pop)

3> Les principaux avertissements utilisés sont les suivants:

une fois: afficher le message une seule fois (avertissement / erreur, etc.)

par défaut: réinitialise le comportement d'avertissement du compilateur à l'état par défaut

1, 2, 3, 4: quatre niveaux d'avertissement

désactiver: interdire le message d'avertissement spécifié

erreur: signaler le message d'avertissement spécifié comme une erreur

Si vous ne comprenez pas très bien l'explication ci-dessus, vous pouvez vous référer à l'exemple et à l'explication suivants

#pragma warning (désactiver: 4507 34; une fois: 4385; erreur: 164) 

Équivalent à: 

#pragma warning (disable: 4507 34) // Ne pas afficher les messages d'avertissement 4507 et 34 

#pragma warning (once: 4385) // Le message d'avertissement n ° 4385 n'est signalé qu'une seule fois 

#pragma warning (error: 164) // Considérez le message d'avertissement 164 comme une erreur. 

Dans le même temps, cet avertissement pragma prend également en charge le format suivant: 

#pragma avertissement (appuyez sur [, n]) 

#pragma avertissement (pop) 

Ici n représente un niveau d'avertissement (1 --- 4). 

#pragma warning (push) Enregistre l'état d'avertissement existant de tous les messages d'avertissement. 

#pragma warning (push, n) enregistre l'état d'avertissement existant de tous les messages d'avertissement et place l'avertissement global 

Le niveau est réglé sur n.  

#pragma warning (pop) Affiche le dernier message d'avertissement dans la pile, ce qui se fait entre l'empilement et le popping 

Toutes les modifications sont annulées. Par exemple: 

#pragma warning (push) 

#pragma warning (désactiver: 4705) 

#pragma warning (désactiver: 4706) 

#pragma warning (désactiver: 4707) 

#pragma avertissement (pop)

À la fin de ce code, enregistrez tous les messages d'avertissement (y compris 4705, 4706 et 4707)

Lorsque vous utilisez C ++ standard pour la programmation, vous recevez souvent de nombreux messages d'avertissement, et ces messages d'avertissement sont des invites inutiles.

Nous pouvons donc utiliser l'avertissement #pragma (désactiver: 4786) pour désactiver ce type d'avertissement

Lorsque vous utilisez ADO dans vc, vous recevrez également des messages d'avertissement inutiles. Pour le moment, nous pouvons transmettre

#pragma warning (disable: 4146) pour éliminer ce type de message d'avertissement

4. # pragma comment (...)

1> fonction:

Cette instruction place un enregistrement de commentaire dans un fichier objet ou un fichier exécutable.

2> Format:

#pragma comment ("comment-type" [, commentstring])

comment-type: peut être spécifié comme l'un des cinq identificateurs prédéfinis

Les cinq identifiants prédéfinis sont:

(1) compilateur: mettez le numéro de version et le nom du compilateur dans le fichier cible, cet enregistrement de commentaire sera ignoré par le compilateur, si vous fournissez le paramètre commentstring pour le type d'enregistrement, le compilateur générera un avertissement

Par exemple: #pragma comment (compilateur)

(2) exestr: Mettez le paramètre commentstring dans le fichier cible, cette chaîne sera placée dans le fichier exécutable lors de la liaison, lorsque le système d'exploitation charge le fichier exécutable, la chaîne de paramètre ne sera pas chargée en mémoire. Cependant, la chaîne peuvent être trouvés et imprimés par des programmes tels que dumpbin. Vous pouvez utiliser cet identifiant pour intégrer des informations telles que le numéro de version dans le fichier exécutable!

(3) lib: C'est un mot-clé très couramment utilisé pour lier un fichier de bibliothèque au fichier cible

Les mots-clés lib couramment utilisés peuvent nous aider à nous connecter à un fichier de bibliothèque. 

Par exemple:

#pragma comment (lib, "user32.lib") 

Cette commande est utilisée pour ajouter le fichier de bibliothèque user32.lib à ce projet

éditeur de liens: mettez une option de lien dans le fichier cible, vous pouvez utiliser cette commande à la place de la ligne de commande ou dans l'environnement de développement

       Pour définir l'option de lien, vous pouvez spécifier l'option / include pour forcer l'inclusion d'un certain objet, par exemple:

      #pragma comment (éditeur de liens, "/ include: __ mySymbol")

Vous pouvez définir les options de lien suivantes dans le programme

/ DEFAULTLIB

/EXPORTATION

/COMPRENDRE

/FUSIONNER

/SECTION

Ces options ne sont pas expliquées ici une par une, veuillez consulter msdn pour plus de détails!

5. # ressource pragma "*. Dfm"

1> fonction:

Cela signifie ajouter les ressources du fichier * .dfm au projet. * .dfm inclut la définition de l'apparence du formulaire.
 

Je suppose que tu aimes

Origine blog.csdn.net/xiaolei251990/article/details/83783194
conseillé
Classement