¿Hay alguna razón por la que alguien incluiría stdlib.h dos veces?

Estaba estudiando el código para el editor de texto Kilo aquí:

https://github.com/antirez/kilo/blob/master/kilo.c

Y me di cuenta de que incluye stdlib.h definido dos veces (ACTUALIZACIÓN: Los comentarios son míos):

 #include  #include  // first time #include  #include  #include  #include  // second time #include  

¿Es esto simplemente un error? ¿O hay algo a eso? Lo pregunto porque el autor del código no parece alguien que cometa muchos errores. No quisiera sugerir un cambio en la ignorancia.

Como stdlib.h tiene un protector incluido, no tiene sentido incluirlo dos veces. Probablemente el error se debió a la combinación de dos archivos, ambos dependientes de stdlib.h.

No hay ningún daño en incluir un encabezado estándar más de una vez, aunque es totalmente innecesario.

El estándar C dice lo siguiente sobre esto:

Los encabezados estándar pueden incluirse en cualquier orden; cada uno puede incluirse más de una vez en un ámbito dado, sin que el efecto sea diferente de ser incluido solo una vez, excepto que el efecto de incluir depende de la definición de NDEBUG .

No hay razón para incluir un archivo de encabezado particular dos veces. Si el archivo tiene guardias de inclusión adecuadas, la segunda inclusión no tendrá ningún efecto. Si no tiene guardas de inclusión, es probable que obtenga una gran cantidad de errores para múltiples definiciones para typedefs, entre otros.

En el caso de los encabezados del sistema, casi siempre tienen guardas incluidos. El contenido de stdlib.h puede verse algo como esto:

 #ifndef _STDLIB_H #define _STDLIB_H 1 ... // type definitions, #defines, declarations, etc. ... #endif /* stdlib.h */ 

La primera vez que se incluye stdlib.h, #ifndef se evaluará como verdadero, se define _STDLIB_H y el contenido restante se inserta en el archivo que se está comstackndo. La segunda vez que se incluye stdlib.h, #ifndef se evaluará como falso ya que _STDLIB_H está definido y el contenido del archivo entre #ifndef y #endif no se volverá a insertar.

La mayoría de los sistemas UNIX / Linux hacen esto. En contraste, Microsoft es conocido por no administrar sus archivos de inclusión específicos del sistema operativo correctamente. Si los incluyó en el orden incorrecto, terminará con muchos errores.

El único escenario en el que puede marcar la diferencia es cuando uno de los incluidos no está definiendo algunos símbolos (incluidos los guardias de inclusión) de los incluidos anteriores. Considere 2 archivos:
1.h:

 #define A 1 

2.h :

 #undef A 

Ahora, la siguiente secuencia:

 #include "1.h" #include "2.h" int B = A; 

producirá un error, ya que A no está definido.

La siguiente secuencia estará bien:

 #include "1.h" #include "2.h" #include "1.h" int B = A; 

Ahora, si 1.h tiene los guardias incluidos:

1.h:

 #ifndef GUARD_1 #define GUARD_1 #define A 1 #endif 

El 2.h puede hacer:

 #undef GUARD_1 #undef A 

y causar el mismo efecto.

Ahora a stdlib.h . Puedes componer algo como esto en tu encabezado xh :

 #undef _STDLIB_H // Kill the include guard of stdlib.h #undef NULL // Undefine some important symbol from stdlib.h 

Ahora, esta secuencia:

 #include  #include "xh" 

tendrá NULL indefinido

Y esto:

 #include  #include "xh" #include  

Lo tendrá definido.

Aunque no es directamente aplicable a , una razón para incluir un archivo de encabezado definido por el usuario dos veces: probar si incluir el archivo de encabezado dos veces incurre en un problema.

Ejemplo: Considere un par de archivos foo.h y foo.c declarando e implementando un montón de funciones foo_ , definiciones, tipos, etc.

Archivo foo.c

 #include "foo.h" #include "foo.h" rest of foo.c code ... 

Una segunda llamada de un archivo de inclusión no debería causar un problema y foo.c prueba.
OTOH, foo.c no probó si incluir un archivo de encabezado solo una vez está bien.