Bote de lenguaje C 4: use _Pragma para descartar suavemente la API

I. Introducción

Imagine este escenario de trabajo: está escribiendo una biblioteca de funciones para un proyecto , y otros llaman a las funciones proporcionadas en la biblioteca, y luego encuentra que la función A en la biblioteca es
redundante
.

Con una trama perfecta, solo desea descartar esta función A. En este momento , definitivamente no puede eliminarla directamente , porque no sabe cuántas otras personas llamaron a esta función.

¿Cómo afrontar mejor esta situación?

Hablemos de este tema en este breve artículo.

En segundo lugar, el proceso de operación

1. La primera versión de la biblioteca

Solo hay 3 archivos de prueba : api.h, api.cy main.c

  1. api.hy api.c: archivos de biblioteca, libapi.so compilado;
  2. main.c: Genera un programa ejecutable, usando la biblioteca libapi.so generada anteriormente;

api.h contenido de los documentos: una declaración de las dos funciones.

contenido del archivo api.c: la definición de las dos funciones.

Compile el archivo de biblioteca libapi.so . Instrucciones de compilación:

gcc -fPIC -shared api.c -o libapi.so

Contenido del archivo Main.c:

Compile el archivo ejecutable:

gcc main.c -o main -L./ -Wl,-rpath=./ -lapi

La simplicidad del código anterior es equivalente a helloworld.

2. La segunda versión de la biblioteca

Ahora, cree que la función init es redundante . Si desea eliminarla, puede modificarla de esta manera.

En el archivo api.c , elimine la función init ().

El contenido del archivo api.h se cambia a lo siguiente:

El código clave es esta línea:

#define init()               (1) API_DEPRECATED

Ahora que el archivo api.c ha eliminado esta función , pero esta función se llama en el archivo main.c, el símbolo de inicio se proporciona en forma de definición de macro .

En otras palabras:

En la primera versión, init en el archivo main.c es una función , que es procesada por el compilador, y la dirección de esta función se encuentra en la biblioteca libapi.so durante la fase de enlace ;

En la segunda versión, init se define como una macro , que es reemplazada por esta última en la etapa de preprocesamiento(1) API_DEPRECATED .

(1) es la expresión en la macro sustitución. Debido a que esta función se puede utilizar para juzgar las condiciones if, debe devolver un valor.
API_DEPRECATED es otra definición de macro, que se amplía para permitir que el compilador imprima un mensaje al compilar el programa ejecutable.

Al compilar el archivo ejecutable, el compilador genera el siguiente párrafo:

gcc main.c -o main -L./ -Wl,-rpath=./ -lapi

¡Esto ha logrado el propósito original! Eso es para recordarle al usuario: esta función ha sido obsoleta, ¡es mejor no usarla!

Tres _Prama otro uso

_Pragma es similar a la palabra clave __pragma específica de Microsoft, excepto que es parte del estándar. Fue introducido para C en C99 . Para c ++, se introdujo en c ++ 11.
Permite colocar instrucciones en definiciones de macros.

1. Manejo de la inclusión repetida de archivos de encabezado

En el archivo de encabezado, para evitar la inclusión repetida , generalmente hay 3 formas de tratarlo:

(1) El primer enfoque:

#ifdef   MY_API
#define  MY_API

// 头文件内容

#endif

(2) El segundo método de procesamiento

#pragma once

// 头文件内容

Los dos métodos anteriores pueden evitar que el mismo archivo de encabezado se incluya repetidamente, pero aún existen algunas diferencias .

La primera forma: el preprocesador aún necesita buscar el archivo, luego abrir el archivo y, después de leer el contenido del archivo, verificar si se ha definido MY_API.

La segunda forma: puede acelerar la velocidad de compilación, porque este es un mecanismo de gama alta; el compilador comparará automáticamente el nombre del archivo , sin la necesidad de juzgar #ifndef y #endif en el archivo de encabezado, de modo que la búsqueda intermedia se omite , abre y lee las operaciones.

(3) El tercer enfoque

_Pragma("once")

La diferencia entre este método y el segundo método es:

#pragma: es una instrucción de preprocesamiento, que se utiliza para transmitir alguna información fuera del estándar del lenguaje al compilador, y no se puede usar en macros;
_Pragma: es un operador que pertenece al estándar del lenguaje, por lo que se puede anidar en macros, al igual que en el ejemplo anterior;

#pragma es una extensión del compilador, es decir, lo determina el compilador, quizás el compilador A lo soporte, pero el compilador B puede que no lo soporte, aunque esta posibilidad es relativamente pequeña.

El operador _Pragma es un estándar a nivel de lenguaje, ya que es un estándar, el compilador debe seguir el estándar , por lo que también se recomienda este método.

Recuerde que el maestro de Hou Jie dijo en la lección de video de C ++: Escribimos código, no solo para garantizar que funcione correctamente, ¡y ponemos el código escrito en una gran atmósfera ! Siento que usar _Pragma puede ser más atmosférico que #ifndef.

2. Información de compilación de salida

#pragma message("the #pragma way")
_Pragma ("message( \"the _Pragma way\")") 

El contenido y la información de salida de las dos líneas anteriores son iguales. Tenga en cuenta que las comillas dobles anidadas deben escaparse con una barra invertida.

¡Eso es todo! ¡Que tengas un gran fin de semana!


Los buenos artículos deben enviarse ; cuanto más compartas, más afortunado eres.


Lectura recomendada

[Lenguaje C]
1. Puntero del lenguaje C: desde el principio subyacente hasta habilidades sofisticadas, con imágenes y códigos para ayudarlo a explicarlo en profundidad
2. El principio de depuración subyacente de gdb original es muy simple
3. Análisis paso a paso: cómo usar C para lograr la programación orientada a objetos
4. Un arma para mejorar la compulsión de código: definición de macro, desde la entrada hasta el abandono
5. Use setjmp y longjmp en lenguaje C para implementar la captura de excepciones y la co-rutina

[Diseño de la aplicación]
1. Todos dicen que la arquitectura del software debe dividirse en capas y en módulos, y cómo hacerlo (1)
2. Todos dicen que la arquitectura del software debe dividirse en capas y en módulos, y cómo hágalo (2)
3. Desarrollo de pasarela de IoT:
proceso de diseño basado en bus de mensajes MQTT (Parte 1) 4. Desarrollo de pasarela de IoT: proceso de diseño basado en bus de mensajes MQTT (Parte 2)
5. Mi método favorito de comunicación entre procesos-mensaje autobús

[Sistema operativo]
1. ¿Por qué las naves espaciales y los misiles prefieren utilizar microcontroladores en lugar de sistemas integrados?

[Internet de las cosas]
1. Esas cosas sobre el cifrado y los certificados
2. Profundice en el lenguaje de secuencias de comandos LUA, le permitirá comprender completamente el principio de depuración

[Tonterías] 1. Basado
en mi experiencia profesional fallida: algunos consejos para los técnicos que son nuevos en el lugar de trabajo

Supongo que te gusta

Origin blog.csdn.net/u012296253/article/details/115366935
Recomendado
Clasificación