C Typedef y Struct Pregunta

3 minutos de lectura

¿Cuál es la diferencia entre estas dos declaraciones? ¿Se prefiere una sobre la otra?

typedef struct IOPORT {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;  

typedef struct {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;  

el primero le permite usar IOPORT dentro de la estructura para referirse a objetos del mismo tipo. útil en casos como listas enlazadas donde un nodo tiene que hacer referencia a un nodo.

C tiene cuatro espacios de nombres diferentes, donde el espacio de nombres de la etiqueta de estructura es uno de ellos. Por eso:

struct foo { int bar; };

no define un nuevo tipo en el sentido general. Cuando solo tiene una etiqueta de estructura, debe anteponer la palabra clave ‘struct’ en declaraciones de objetos como esta:

foo b; /* error */
struct foo b; /* correct */

Además, puede crear una instancia de un nuevo objeto de inmediato en la definición de esta manera:

struct foo { int bar; } baz;

Donde baz es un objeto de tipo de estructura foo. Sin embargo, a menudo se quiere definir una estructura como un nuevo tipo, para ahorrar algo de escritura. Un tipo completo no hace referencia a las etiquetas de estructura, por lo que puede omitir el prefijo ‘struct’ durante las declaraciones.

typedef struct foo { int bar; } baz;

Todavía te permite declarar objetos con ‘struct foo’, ya que foo es la etiqueta de estructura. Pero ahora se promueve a un tipo completo en el espacio de nombres de tipo “normal”, donde se conoce como tipo baz. Entonces, con un typedef, los campos ‘baz’ tienen una semántica diferente.

A menos que necesite declarar punteros al tipo de estructura dentro de sí mismo (listas enlazadas, estructuras de árbol), omítalo. Agregar uno que no es necesario solo contamina el espacio de nombres.

avatar de usuario
miguel rebabas

En cuanto a qué estilo se prefiere, prefiero el primer estilo (con el nombre tanto en la etiqueta de estructura como en typedef para la estructura) simplemente porque no hay inconvenientes aparte de unos pocos caracteres más en el archivo fuente. El fragmento de estructura de mi IDE deja caer el nombre en ambos lugares, por lo que siempre obtengo un nombre de estructura con tipo definido junto con un nombre de etiqueta de estructura.

Obtienes algunos pequeños beneficios:

  • los “struct STRUCTNAME” puede usarse para declarar punteros a la estructura dentro de la estructura
  • puede salirse con la suya simplemente usando STRUCTNAME en código C o C ++
  • previene una rareza potencial (aunque muy rara en la práctica) en C ++ que tiene que ver con el nombre de la estructura que se usa para otro objeto sin error ni advertencia

Pero, si escribo manualmente la definición de la estructura, a menudo descuidaré perezosamente la declaración de uno u otro nombre.

avatar de usuario
Den-Jason

En aras de la legibilidad, se prefiere expresar el ejemplo original en una forma como:

typedef struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT; 

….que enfatiza la diferencia entre tipo e instancia.

Además, si desea agregar inicializadores, puede hacer algo como:

typedef struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT;

struct IOPORT_t IOPORT2 = {
    .port = NULL,
    .pin = 25
  };

o puedes perder el typedef para inicializarlo directamente:

struct IOPORT_t {  
    GPIO_TypeDef* port;  
    u16           pin;  
} IOPORT = {
    .port = NULL,
    .pin = 24
  };

struct IOPORT_t IOPORT2 = {
    .port = NULL,
    .pin = 25
  };

  • Los identificadores que comienzan con doble guión bajo o guión bajo + letra mayúscula están reservados, por lo que no debe usarlos. Podrían entrar en conflicto con un identificador en el compilador o bibliotecas estándar. Ver stackoverflow.com/a/1449301

    – Neal Gokli

    29 de septiembre de 2016 a las 1:27

¿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