¿Deberían las definiciones de estructura ir en el archivo .h o .c?

5 minutos de lectura

¿Deberian las definiciones de estructura ir en el archivo h
Aaron Yodaiken

He visto ambas definiciones completas de structs en encabezados y solo declaraciones: ¿hay alguna ventaja de un método sobre el otro?

Si hace una diferencia, generalmente tipeo una estructura como esa en el .h

typedef struct s s_t;

Para que quede claro, las opciones son declaración en el archivo de encabezado y definición en la clase, o declaración y definición en el archivo de encabezado. Ambos deberían dar como resultado la misma usabilidad, incluso si uno es por enlace, ¿no?


Veo muchos casi duplicados, por ejemplo aquí, pero no hay coincidencias exactas. Por favor corrígeme si me equivoco en este sentido.

  • ¿Quieres una estructura opaca o no opaca?

    usuario142019

    11 de junio de 2011 a las 16:14

  • Nota al margen, identificadores con _t están reservados por POSIX, por lo que suele ser una mala idea. Podrías simplemente hacer typedef struct toto toto.

    – Jens Gusted

    11 de junio de 2011 a las 16:22

  • he visto muchos _t use otros lugares (por ejemplo, lighttp, linux) … y prefijo las cosas con projident_ entonces, eso no debería ser un problema, ¿verdad?

    – Aarón Yodaiken

    11 de junio de 2011 a las 16:26

  • Y @WTP, creo que lo no opaco generalmente se considera mejor y más Cish, no (lo que con el FILE ejemplo, etc.). Entonces, no opaco.

    – Aarón Yodaiken

    11 de junio de 2011 a las 16:27

  • Si es una estructura no opaca, debe ir en un archivo de encabezado, o su código no está SECO (no se repita).

    usuario142019

    11 de junio de 2011 a las 17:49


Las estructuras privadas para ese archivo deben ir en el archivo .c, con una declaración en el archivo .h si son utilizadas por alguna función en el .h.

Las estructuras públicas deben ir en el archivo .h.

  • Creo que estoy más de acuerdo con esta respuesta. No se trata de usar la estructura a través de otros archivos .c o no, sino de si la estructura debe considerarse pública (y, por lo tanto, accesible) o no.

    – c00kiemon5ter

    11 de junio de 2011 a las 16:21


  • @τεκ ¿Quieres decir global y local ¿visibilidad? public no tiene sentido en una estructura. Todas las estructuras son públicas por defecto.

    – BugShotGG

    6 de julio de 2015 a las 16:05

  • @Geo Papas Esta es una pregunta sobre C. public no es una palabra clave en C. Si observa la respuesta de Matthew Slattery a continuación, puede ver cómo usar solo una declaración directa en el encabezado provoca un error del compilador cuando el usuario intenta usar miembros de una estructura privada (opaca).

    – τεκ

    6 de julio de 2015 a las 23:37

Ambos deberían dar como resultado la misma usabilidad, incluso si uno es por enlace, ¿no?

No, no cuando considera otros archivos .c que incluyen el mismo encabezado. Si la definición de la estructura no es visible para el compilador, los detalles de esa definición no se pueden usar. Una declaración sin una definición (por ejemplo, simplemente struct s;) hace que el compilador falle si algo intenta mirar dentro struct ssin dejar de permitirle, por ejemplo, compilar struct s *foo; (siempre y cuando foo no se desreferencia posteriormente).

Compara estas versiones de api.h y api.c:

Definition in header:                 Definition in implementation:
+---------------------------------+   +---------------------------------+
| struct s {                      |   | struct s;                       |
|     int internal;               |   |                                 |
|     int other_stuff;            |   | extern void                     |
| };                              |   | api_func(struct s *foo, int x); |
|                                 |   +---------------------------------+
| extern void                     |   +---------------------------------+
| api_func(struct s *foo, int x); |   | #include "api.h"                |
+---------------------------------+   |                                 |
+---------------------------------+   | struct s {                      |
| #include "api.h"                |   |     int internal;               |
|                                 |   |     int other_stuff;            |
| void                            |   | };                              |
| api_func(struct s *foo, int x)  |   |                                 |
| {                               |   | void                            |
|     foo->internal = x;          |   | api_func(struct s *foo, int x)  |
| }                               |   | {                               |
+---------------------------------+   |     foo->internal = x;          |
                                      | }                               |
                                      +---------------------------------+

Este cliente de la API funciona con cualquiera de las dos versiones:

#include "api.h"

void good(struct s *foo)
{
    api_func(foo, 123);
}

Este hurga en los detalles de implementación:

#include "api.h"

void bad(struct s *foo)
{
    foo->internal = 123;
}

que funcionará con la versión “definición en encabezado”, pero no con la versión “definición en implementación”, ya que en este último caso el compilador no tiene visibilidad del diseño de la estructura:

$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$

Por lo tanto, la versión de “definición en implementación” protege contra el mal uso accidental o deliberado de los detalles de implementación privados.

  • solo quiero saber cómo creó esas ventanas de código y todavía tiene el código resaltado dentro de ellas… ¿manualmente? Este OP parece haberse ido usando stackoverflow :'( ¿Alguien más puede decirme…?

    – Mahesha999

    24/03/2016 a las 17:36


  • ¡Buen ejemplo! ¡Gracias!

    – Víctor H.

    2 de abril de 2016 a las 4:36

  • ¡Gracias por tal ejemplo! dereferencing pointer to incomplete type fue exactamente mi caso!

    – Timur Fayzrakhmanov

    11 de noviembre de 2016 a las 8:00

  • Solo me gustaría agregar que no todas las estructuras de acceso público son malas: por ejemplo, es posible que desee permitir que el usuario de su API complete datos y los envíe.

    – Alexander Torstling

    24 de febrero de 2017 a las 16:27

  • @ Mahesha999, no hay magia ahí. SO resalta el código incluso si pones basura en él. Obsérvelo tratando de resaltar la salida de la línea de comando más adelante en la publicación.

    – alero

    4 de enero de 2018 a las 14:53

Si la estructura va a ser utilizada por otras unidades de compilación (archivos .c), colóquela en el archivo de encabezado para que pueda incluir ese archivo de encabezado donde sea necesario.

Si la estructura solo se usa en una unidad de compilación (archivo .c), la coloca en ese archivo .c.

El punto es que colocarlo en un archivo de encabezado le permite usar la estructura (o cualquier otra definición) de múltiples archivos fuente, simplemente incluyendo ese archivo de encabezado.

Pero si está seguro de que solo se usará desde un archivo fuente, entonces realmente no hace ninguna diferencia.

Los puse en el archivo C para hacerlo más orientado a objetos, ver este artículo.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad