¿Por qué mis guardias de comstackción no previenen múltiples inclusiones de definición?

Tengo un archivo de encabezado xh que está incluido en más de un archivo fuente * .c. Este archivo de encabezado tiene algunas variables de estructura definidas.

He puesto múltiples guardias de prevención de inclusión al comienzo del archivo de encabezado como:

#ifndef X_H #define X_H ... .. //header file declarations and definitons. #endif//X_H 

En la construcción recibo errores de enlazador relacionados con múltiples definiciones. Entiendo el problema

  1. ¿No habrá un protector de prevención de inclusión múltiple en la parte superior del archivo de encabezado como lo tengo, evitará múltiples inclusiones del archivo de encabezado xh y, por lo tanto, evitará las múltiples definiciones de las variables que están en xh?

  2. #pragma una vez no funciona en este comstackdor en particular, ¿cuál es la solución? Alguien había publicado esta respuesta a una pregunta similar. No parece funcionar para mí. ¿Cómo funciona esta solución?

Si el enlazador se queja, significa que tiene definiciones en lugar de solo declaraciones en su encabezado. Aquí hay un ejemplo de cosas que estarían mal.

 #ifndef X_H #define X_H int myFunc() { return 42; // Wrong! definition in header. } int myVar; // Wrong! definition in header. #endif 

Debe dividir esto en el archivo de fuente y encabezado como este:

Encabezamiento:

 #ifndef X_H #define X_H extern int myFunc(); extern int myVar; #endif 

Fuente C:

 int myFunc() { return 42; } int myVar; 

El uso de incluir guardias evita que una unidad de comstackción incluya el encabezado dos veces. Por ejemplo, si el encabezado Bh incluye Ah y B.cpp incluye Ah y Bh, todo lo de Ah se declararía dos veces en la comstackción B.cpp si no usa protectores de inclusión.

Sus guardias de inclusión evitan que esto suceda, todo está bien hasta ahora.

Pero obtiene múltiples definiciones en tiempo de enlace, es decir, dos unidades de comstackción definen lo mismo, esto probablemente significa que tiene una definición real en su encabezado, use extern para todas las variables, asegúrese de que las funciones estén en línea o definidas en el archivo cpp.

Las protecciones de encabezado solo son buenas para una sola unidad de comstackción, es decir, el archivo fuente. Si por casualidad incluye un archivo de encabezado varias veces, tal vez porque todos los encabezados incluidos desde main.c a su vez incluyen stdio.h , los guardias lo ayudarán.

Si tiene la definición de una función f en xh que está incluida en main.c y util.c , entonces es como copiar y pegar la definición de f en main.c al crear main.o y hacer lo mismo para util.c para crear util.o Entonces el enlazador se quejará y esto sucede a pesar de los guardias de tu encabezado. Tener múltiples instrucciones #include "xh" en main.c es posible por supuesto debido a estas guardias.

Si las funciones no son grandes, puede usar “en línea” antes de ellas y el vinculador no se quejará.

El uso de un protector de inclusión múltiple previene los errores del comstackdor , pero está obteniendo un error del enlazador. ¿Tiene definiciones de datos en el archivo de encabezado que no usan extern ?

¿Tal vez X_H ya está definido en otro lugar? Acabo de X_H con este problema, donde Xlib define X_H en / usr / include / X11 / Xh

Para verificar, puede llamar a gcc -dM -E (si está usando gcc), por ejemplo, en el sistema de comstackción que estoy usando que funciona con CC=gcc CFLAGS="-dM -E" make . Si el archivo de salida contiene #define X_H aunque lo elimine de su archivo (use Y_H por ejemplo), entonces ya está definido fuera de su código fuente.