Uso de #pragma en Linux

Uso de la directiva #pragma precompilada

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

Al mirar el código en un proyecto de código abierto recientemente, descubrí que los programas #pragma se usan en muchos lugares. Por lo tanto, le pregunté al profesor de Google y resumí el uso común de las instrucciones precompiladas de #pragma. Ahora las compartiré con ustedes.

1. #pragma el método más utilizado

1. #progma pack (n)

1> Función:

Use la directiva de precompilación #progma pack para cambiar el valor predeterminado del compilador (no absoluto, algunos compiladores solo pueden usar alineación de datos fija).

2> Descripción

En la mayoría de los casos, no consideramos los problemas de alineación cuando escribimos programas, porque el compilador elegirá la estrategia adecuada para nosotros. La mayoría de los compiladores utilizan la alineación de cuatro bytes de forma predeterminada.

Puede ver un programa para comprender:

Procedimiento A:

#include <stdio.h>

estructura A

{

    int a;

    char b;

    c corta;   

};

int main ()

{

    int d;

    d = tamaño de (estructura A);

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

     return 0;

}

Nota:

(1) Generalmente, usamos procesadores de 32 bits y el número de bytes de alineación predeterminado del compilador vc es de 4 bytes. En gcc, de forma predeterminada, el tipo de variable más grande en la estructura está alineado por bytes.

La estructura A contiene un int con una longitud de 4 bytes, un char con una longitud de 1 byte y un dato corto con una longitud de 2 bytes. Entonces, el espacio usado por A debería ser de 7 bytes. Pero porque el compilador necesita alinear los miembros de datos en el espacio. Por lo tanto, use el valor de sizeof (strcut A) de 8 "a ocupa 4 bytes, b ocupa un byte yc ocupa dos bytes, por lo que el compilador colocará by C en uno de 4 bytes, por lo que la estructura Cuerpo A ocupa 8 bytes"

(2) Ahora discutimos los beneficios de la alineación de bytes:

El espacio de memoria en las computadoras modernas se divide en bytes. En teoría, parece que el acceso a cualquier tipo de variable puede comenzar desde cualquier dirección, pero la situación real es que cuando se accede a una variable específica, a menudo se accede a una memoria específica. Todos los tipos de datos deben organizarse en el espacio de acuerdo con ciertas reglas, en lugar de organizarse uno tras otro en orden, esto es alineación

 

El papel y la razón de la alineación: el procesamiento del espacio de almacenamiento por varias plataformas de hardware es muy diferente. Algunas plataformas solo pueden acceder a ciertos tipos de datos desde ciertas direcciones específicas. Es posible que otras plataformas no tengan esta situación, pero lo más común es que si el almacenamiento de datos no está alineado según los requisitos de la plataforma, provocará una pérdida en la eficiencia de acceso

 

Por ejemplo, algunas plataformas comienzan con una dirección par cada vez. Si un tipo int (asumiendo un sistema de 32 bits) se almacena al comienzo de la dirección par, entonces se puede leer un ciclo de lectura, y si se almacena en el dirección impar. En algunos lugares, pueden ser necesarios 2 ciclos de lectura y unir los bytes altos y bajos de los dos resultados de lectura para obtener los datos int. Evidentemente, la eficiencia de lectura ha bajado mucho. Este es también un juego entre el espacio y el tiempo.

3> ¿Cómo utilizar?

Ejemplos de uso:
#pragma pack (push) // Guarde el estado de alineación anterior, push es empujar el estado de alineación anterior a la pila  
#pragma pack (1) // Especifique el nuevo estado de alineación, 1 byte
// defina usted El estructura de  
// …………  
#pragma pack (pop) // Pop la pila y restaurar el estado de alineación anterior

Ahora modificamos el programa ahora mismo:

Procedimiento B:

#include <stdio.h>

 

# paquete de pragma (empujar)

#paquete de pragma (1)

 

estructura A

{

    int a;

    char b;

    c corta;   

};

# paquete de pragma (pop);

int main ()

{

    int d;

    d = tamaño de (estructura A);

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

     return 0;

}

En este momento, debido a que está alineado por un byte, la estructura A ocupa un total de 7 bytes.

2. #pragma message ("cadena constante")

1> Función:

Cuando el compilador encuentra esta instrucción, imprime el texto del mensaje en la ventana de salida de la compilación.

2> Descripción:

Cuando definimos muchas macros en el programa para controlar la versión del código fuente, es posible que olvidemos si las hemos configurado correctamente. En este momento, podemos usar esta instrucción para verificar la compilación.

3> ¿Cómo utilizar?
# mensaje pragma ("macro activada!")

Nota: Aquí no hay punto y coma después del mensaje ().

3. # pragma once

1> Función:

Simplemente agregue esta instrucción al principio del archivo de encabezado para asegurarse de que el archivo de encabezado se compile una vez

2> Nota: la diferencia entre #pragma once y #ifndef

(1) Similitudes:

Para evitar que el mismo archivo se incluya varias veces, no hay mucha diferencia entre el modo #ifndef y el modo #pragma una vez (siempre que el compilador pueda admitir ambos modos al mismo tiempo).

(2) Cómo utilizar ambos:

método uno:

#ifndef __TIGER_H__

#define __TIGER_H__

……… .// Algunas declaraciones de declaración

#terminara si

Método dos:

#pragma once

……… // Algunas declaraciones de declaración

(3) La diferencia entre los dos:

El método de #ifndef se basa en el hecho de que los nombres de las macros no pueden entrar en conflicto. Esto no solo garantiza que el mismo archivo no se incluirá varias veces, sino también que dos archivos de encabezado con el mismo contenido no se incluirán accidentalmente al mismo tiempo. . Por supuesto, la desventaja es que si los nombres de macro de diferentes archivos de encabezado "fallan" accidentalmente, puede causar que existan los archivos de encabezado, pero el compilador insiste en que no se puede encontrar la declaración.

#pragma once está garantizado por el compilador: el mismo archivo no se incluirá varias veces. Tenga en cuenta que el mismo archivo mencionado aquí se refiere a un archivo físico, no a dos archivos con el mismo contenido. La ventaja es que ya no tiene que pensar en un nombre de macro y, por supuesto, no habrá problemas extraños causados ​​por las colisiones de nombres de macros. La desventaja correspondiente es que si hay varias copias de un archivo de encabezado, este método no puede garantizar que no se incluirán repetidamente. Por supuesto, en comparación con el problema de "declaración no encontrada" causado por las colisiones de nombres de macros, las inclusiones repetidas son más fáciles de encontrar y corregir.

Para #pragmaonce, según MSDN, puede evitar que un archivo se incluya varias veces. En comparación con la protección de archivos en forma de #ifndef #define #endif, la primera depende de la plataforma y tiene poca portabilidad, pero es más eficiente porque no necesita abrir el archivo incluido para determinar si el archivo se ha incluido. Por supuesto, este trabajo lo realiza el sistema. La ventaja de este último es que es una característica relacionada con el idioma, por lo que la portabilidad es buena. Pero al incluir un archivo, solo abra el archivo y juzgue si el archivo se ha incluido en función de si se ha definido la macro de protección del archivo. La eficiencia es relativamente baja. Por supuesto, cuando #include, el programador también puede juzgar si se ha definido la macro de protección del archivo a incluir, para decidir si incluir el archivo. Similar al siguiente código:

#ifndef FILE_H_

#Incluya "archivo.h"

#terminara si

Esto puede lograr una mayor eficiencia y garantizar la portabilidad. Sin embargo, la dependencia entre archivos es alta, si se cambia la macro de protección de un archivo, se deben modificar todos los archivos que contengan este archivo en el formato anterior. Contrario a la idea de modularidad.

2. #pragma algunos otros métodos

1. El parámetro #pragma es code_seg.

1> Formato: 

#pragma code_seg ([[{push | pop},] [identificador,]] ["nombre-segmento" [, "clase-segmento"])

2> Función:

Puede configurar el segmento de código del código de función en el programa, que se utilizará cuando desarrollemos el controlador

3> Descripción:

Esta instrucción se usa para especificar la sección donde se almacena la función en el archivo .obj. Para observar el archivo OBJ, puede usar el programa de línea de comando dumpbin que viene con VC. La sección de almacenamiento predeterminada de la función en el archivo .obj es la sección .text, si code_seg no toma parámetros., La función se almacena en la sección .text. push (parámetro opcional) Coloca un registro en la pila del compilador interno. El parámetro opcional puede ser un identificador o un nombre de sección. pop (parámetro opcional) Extrae un registro de la parte superior de la pila. El registro puede ser un identificador o un nombre de sección. identificador (parámetro opcional) Cuando se usa la instrucción push, se asigna un identificador al registro insertado en la pila. Cuando se elimina el identificador, el registro en la pila asociado con él se extraerá de la pila. "nombre-segmento" (parámetro opcional) representa el nombre de la sección donde se almacena la función

3> Ejemplo:

// Por defecto, las funciones se almacenan en la sección .text

void func1 () {// almacenado en .text

}

 

// Almacena la función en la sección .my_data1

#pragma code_seg (". my_data1")

void func2 () {// almacenado en my_data1

}

 

// r1 es el identificador, coloca la función en la sección .my_data2

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

void func3 () {// almacenado en my_data2

}

 

int main () {

}

2. # pragma hdrstop

1> Función:

Indica que el archivo de encabezado precompilado termina aquí, los siguientes archivos de encabezado no están precompilados, BCB puede precompilar los archivos de encabezado para acelerar el enlace, pero si todos los archivos de encabezado están precompilados, también puede ocupar mucho espacio en disco, así que use esta opción para excluir algunos archivos de encabezado. 

A veces hay dependencias entre unidades, por ejemplo, la unidad A depende de la unidad B, por lo que la unidad B debe compilarse antes que la unidad A. Puede usar #pragma startup para especificar la prioridad de compilación. Si se usa el paquete #pragma (smart_init), BCB se compilará de acuerdo con la prioridad. 
3. # advertencia de pragma

1> Función:

Esta directiva permite modificar selectivamente el comportamiento de los mensajes de advertencia del compilador.

2> Formato de comando:

#pragma advertencia (especificador-advertencia: lista-números-advertencia [; especificador-advertencia: lista-números-advertencia ...]

# advertencia de pragma (presione [, n])

#pragma warning (pop)

3> Las principales advertencias utilizadas son las siguientes:

una vez: muestra el mensaje solo una vez (advertencia / error, etc.)

predeterminado: restablece el comportamiento de advertencia del compilador al estado predeterminado

1,2,3,4: Cuatro niveles de advertencia

deshabilitar: prohíbe el mensaje de advertencia especificado

error: informa el mensaje de advertencia especificado como un error

Si no comprende muy bien la explicación anterior, puede consultar el siguiente ejemplo y explicación

# advertencia de pragma (deshabilitar: 4507 34; una vez: 4385; error: 164) 

Equivalente a: 

#pragma warning (deshabilitar: 4507 34) // No mostrar los mensajes de advertencia 4507 y 34 

#pragma warning (once: 4385) // El mensaje de advertencia No. 4385 solo se informa una vez 

#pragma warning (error: 164) // Considere el mensaje de advertencia 164 como un error. 

Al mismo tiempo, esta advertencia de pragma también admite el siguiente formato: 

# advertencia de pragma (presione [, n]) 

#pragma warning (pop) 

Aquí n representa un nivel de advertencia (1 --- 4). 

#pragma warning (push) Guarda el estado de advertencia existente de todos los mensajes de advertencia. 

#pragma warning (push, n) guarda el estado de advertencia existente de todos los mensajes de advertencia y coloca la advertencia global 

El nivel se establece en n.  

#pragma warning (pop) Muestra el último mensaje de advertencia en la pila, que se realiza entre el apilado y el estallido. 

Todos los cambios están cancelados. P.ej: 

#pragma warning (push) 

#pragma warning (deshabilitar: 4705) 

#pragma warning (deshabilitar: 4706) 

#pragma warning (deshabilitar: 4707) 

#pragma warning (pop)

Al final de este código, guarde todos los mensajes de advertencia (incluidos 4705, 4706 y 4707)

Cuando usa C ++ estándar para la programación, a menudo recibe muchos mensajes de advertencia, y estos mensajes de advertencia son indicaciones innecesarias.

Entonces podemos usar #pragma warning (deshabilitar: 4786) para deshabilitar este tipo de advertencia

Cuando use ADO en vc, también recibirá mensajes de advertencia innecesarios. En este momento, podemos pasar

#pragma warning (deshabilitar: 4146) para eliminar este tipo de mensaje de advertencia

4. # pragma comentario (...)

1> Función:

Esta instrucción coloca un registro de comentario en un archivo objeto o archivo ejecutable.

2> Formato:

#pragma comentario ("tipo de comentario" [, cadena de comentarios])

tipo de comentario: se puede especificar como uno de los cinco identificadores predefinidos

Los cinco identificadores predefinidos son:

(1) compilador: coloque el número de versión y el nombre del compilador en el archivo de destino, este registro de comentarios será ignorado por el compilador, si proporciona el parámetro de cadena de comentarios para el tipo de registro, el compilador generará una advertencia

Por ejemplo: #pragma comment (compilador)

(2) exestr: coloque el parámetro de la cadena de comentarios en el archivo de destino, esta cadena se colocará en el archivo ejecutable al vincular, cuando el sistema operativo cargue el archivo ejecutable, la cadena del parámetro no se cargará en la memoria. Sin embargo, la cadena puede ser encontrado e impreso por programas como dumpbin ¡Puede usar este identificador para incrustar información como el número de versión en el archivo ejecutable!

(3) lib: esta es una palabra clave muy utilizada para vincular un archivo de biblioteca al archivo de destino

Las palabras clave lib de uso común pueden ayudarnos a conectarnos a un archivo de biblioteca. 

P.ej:

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

Este comando se usa para agregar el archivo de biblioteca user32.lib a este proyecto

enlazador: coloque una opción de enlace en el archivo de destino, puede usar este comando en lugar de la línea de comandos o en el entorno de desarrollo

       Para configurar la opción de enlace, puede especificar la opción / incluir para forzar la inclusión de un determinado objeto, por ejemplo:

      #pragma comment (vinculador, "/ include: __ mySymbol")

Puede configurar las siguientes opciones de enlace en el programa

/ DEFAULTLIB

/EXPORTAR

/INCLUIR

/UNIR

/SECCIÓN

Estas opciones no se explican aquí una por una; consulte msdn para obtener más detalles.

5. # recurso pragma "*. Dfm"

1> Función:

Significa agregar los recursos en el archivo * .dfm al proyecto. * .dfm incluye la definición de la apariencia del formulario.
 

Supongo que te gusta

Origin blog.csdn.net/xiaolei251990/article/details/83783194
Recomendado
Clasificación