He visto estructuras C declaradas de varias maneras antes. ¿Por qué es eso y qué, en todo caso, hace cada uno diferente?
Por ejemplo:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}

chris lutz
Bueno, la diferencia obvia se demuestra en su main
:
struct foo a;
bar b;
baz c;
La primera declaración es de untypedef
educar struct
y necesita la struct
palabra clave a utilizar. El segundo es de un typedef
ed anonimo struct
y así usamos el typedef
nombre. El tercero combina tanto el primero como el segundo: su ejemplo usa baz
(que es convenientemente corto) pero podría usar con la misma facilidad struct _baz
al mismo efecto.
Actualización: la respuesta de larsmans menciona un caso más común en el que debe usar al menos struct x { }
para hacer una lista enlazada. El segundo caso no sería posible aquí (a menos que abandones la cordura y uses un void *
en cambio) porque el struct
es anónimo y el typedef
no sucede hasta el struct
está definido, lo que no le da forma de hacer un puntero (con seguridad de tipos) al struct
escriba en sí mismo. La primera versión funciona bien para este uso, pero en mi experiencia generalmente se prefiere la tercera. Dale algo de reputación por eso.
Una diferencia más sutil está en la ubicación del espacio de nombres. C ª, struct
las etiquetas se colocan en un espacio de nombres separado de otros nombres, pero typedef
los nombres no lo son. Entonces lo siguiente es legal:
struct test {
// contents
};
struct test *test() {
// contents
}
Pero el siguiente no lo es, porque sería ambiguo cuál es el nombre test
es:
typedef struct {
// contents
} test;
test *test() {
// contents
}
typedef
acorta el nombre (siempre es una ventaja), pero lo coloca en el mismo espacio de nombres que sus variables y funciones. Por lo general, esto no es un problema, pero es una diferencia sutil más allá del simple acortamiento.
Es en gran medida una cuestión de preferencia personal. Me gusta dar a los nuevos tipos un nombre que comience con una letra mayúscula y omita el struct
así que suelo escribir typedef struct { ... } Foo
. Eso significa que no puedo escribir struct Foo
.
La excepción es cuando un struct
contiene un puntero a su propio tipo, por ejemplo
typedef struct Node {
// ...
struct Node *next;
} Node;
En este caso, también debe declarar el struct Node
tipo, ya que el typedef
no está dentro del alcance de la struct
definición. Tenga en cuenta que ambos nombres pueden ser iguales (no estoy seguro de dónde se originó la convención de guión bajo, pero supongo que los compiladores de C más antiguos no pudieron manejar typedef struct X X;
).
Todos sus usos son sintácticamente correctos. Prefiero el siguiente uso
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Obsérvese que esto permite utilizar fácilmente el typedef
ya dentro de la declaración de la struct
mismo, y que incluso para struct
que se refieren mutuamente.

mike t
La confusión surge porque algunas de las declaraciones de hecho declaran hasta tres construcciones C. Debes tener en cuenta la diferencia entre:
- Una declaración typedef,
- Una definición de estructura, y
- Una declaración de estructura.
Todos son construcciones de C muy diferentes. Todos hacen cosas diferentes; pero puede combinarlos en una construcción compuesta, si lo desea.
Veamos cada declaración a su vez.
struct foo {
short a;
int b;
float c;
};
Aquí estamos usando la sintaxis de definición de estructura más básica. Estamos definiendo un tipo C y le damos el nombre foo
en el etiqueta espacio de nombres Posteriormente se puede usar para declarar variables de ese tipo usando la siguiente sintaxis:
struct foo myFoo; // Declare a struct variable of type foo.
Esta siguiente declaración le da al tipo otro nombre (alias) en el global espacio de nombres Desglosémoslo en sus componentes usando la declaración básica anterior.
typedef foo bar; // Declare bar as a variable type, the alias of foo.
bar myBar; // No need for the "struct" keyword
¡Ahora simplemente reemplace “foo” con la definición de la estructura y listo!
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
La sintaxis anterior es equivalente a la siguiente secuencia de declaraciones.
struct _baz {
short a;
int b;
float c;
}
typedef _baz baz; // Declare baz as an alias for _baz.
baz myBaz; // Is the same as: struct _baz myBaz;
Esto no responde a su pregunta para C, pero creo que todos son correctos para C++, aunque se prefiere el primero. Esto también puede haber cambiado entre diferentes versiones de C, pero dejaré que alguien más hable de eso, ya que no soy un experto en la historia de C/C++.
– Merlyn Morgan-Graham
15 de enero de 2011 a las 8:10
C++ es diferente: cuando escribes
struct Foo { };
oclass Foo { };
ahí, obtienesFoo
gratis sintypedef
.– Fred Foo
15 de enero de 2011 a las 8:18
Sin embargo, todos seguirán funcionando, aunque pueden hacer cosas ligeramente diferentes (como contaminar su espacio de nombres con etiquetas adicionales).
– Merlyn Morgan-Graham
15 de enero de 2011 a las 8:20
@Merlyn – No exactamente.
class X
te permite declararX x;
peroX
todavía está en elclass
/struct
espacio de nombres de etiquetas, que permite a las personas probar cosas desagradables comoclass singleton { ... } singleton;
– Chris Lutz
15 de enero de 2011 a las 8:30
Tenga en cuenta que el uso de guiones bajos iniciales en los nombres de las etiquetas de estructuras es casi seguro que es incorrecto. Puede romper cosas y no sirve para nada. no lo hagas
– R.. GitHub DEJA DE AYUDAR A ICE
15 de enero de 2011 a las 13:14