Estoy confundido acerca de estas dos estructuras de diferentes tutoriales:
typedef struct complex { float real; float imag; } COMPLEX; typedef struct { float real; float imag; } COMPLEX; COMPLEX c1; ¿Son ambos correctos? ¿Por qué? y ¿es necesario agregar la minúscula de complex antes de estructura? ¿Qué es la situación general?
Con el primero puede usar el alias de tipo COMPLEX o struct complex .
Con el segundo, tiene una estructura anónima que solo se puede usar con el alias de tipo COMPLEX .
Dicho esto, en C++ cualquier nombre de estructura también es un nombre de tipo y se puede usar como tipo directamente:
struct complex { ... }; complex c1;typedef struct complex{ float real; float imag; }COMPLEX; Esta es una struct complex que se ha definido como COMPLEX . Ahora puede usar tanto struct complex c1; y COMPLEX c1; . Como etiquetó esta pregunta C ++, también puede usar complex c1; ya que la struct (y por lo tanto, el typedef para evitarlo) no es necesaria en C++.
typedef struct { float real; float imag; }COMPLEX; Esta es una estructura sin nombre , definida como COMPLEX . Ahora puede usar COMPLEX c1; .
Hasta aquí la diferencia entre estas dos (C) construcciones.
Como etiquetó esta pregunta C ++, lo correcto sería usar las características del encabezado C ++ <complex> :
std::complex< float > c1;Esto se debe realmente a que el sistema de tipos cambió sutilmente entre C y C++. Las estructuras definidas por el usuario (y enumeraciones) en C tenían "etiquetas", que se trataban como diferentes de los tipos.
etiqueta de estructura {/*algunos miembros*/};
typedef struct Tipo de etiqueta; /* Tag y Type pueden tener el mismo nombre */
Esta forma de trabajar todavía es compatible, como muestra su ejemplo, pero C++ agregó una nueva regla que dice que las etiquetas de estructura también son siempre tipos. Por lo tanto, visto desde el punto de vista de C, es como si el compilador de C++ agregara el typedef por usted. Por lo tanto, en C++ ya no necesita decir "estructura" antes de declarar la variable de su tipo de estructura.
Así que sí, ambas formas son "correctas", una es la antigua forma de C y funcionará tanto en C como en C++, la otra es la forma nativa de C++ y no se compilará en C. Es posible que su ejemplo necesite compatibilidad con C para algunos del código, pero no todos.
Si necesita compatibilidad con C, debe usar el patrón anterior, pero no es una práctica común usarlo para el código C++ nativo.
La definición de estructura es la siguiente:
struct type_name { member_type1 member_name1; member_type2 member_name2; . . } object_names;usa un nombre para el nombre de la estructura y el nombre del objeto. puede usar el objeto en el lado de la definición de la estructura sin declarar un nombre para la estructura
Piense en "espacios de nombres" aquí: los nombres de estructuras viven en su propio espacio de nombres.
struct complex { float real; float imag; }; struct complex myvar; // in C and C++ complex myvar // only in C++! C++ también resuelve etiquetas de estructura (si no es posible de otro modo), donde C no lo hace. typedef define un alias para un nombre de tipo, es decir
typedef struct complex COMPLEX; definirá un nuevo nombre COMPLEX que es un sustituto de struct complex .
Esta declaración
typedef struct complex { float real; float imag; } COMPLEX;es una abreviatura de
struct complex { float real; float imag; }; typedef struct complex COMPLEX;También puede omitir la etiqueta de estructura por completo
typedef struct { float real; float imag; } COMPLEX;al igual que en
struct { float real; float imag; } myvar; que define una variable myvar con un tipo de estructura sin nombre.
No hay nada como el lenguaje C/C++.
C ª.
typedef struct complex { float real; float imag; } COMPLEX; COMPLEX c1; struct complex c2; Alias struct complex para escribir COMPLEX
typedef struct{ float real; float imag; } COMPLEX; COMPLEX c1; Estructura de alias sin etiquetas para escribir COMPLEX
¿Cuál es la diferencia práctica?
Como ves usando el primero puedes definir nuevos objetos usando el nuevo tipo COMPLEX y struct complex .
La declaración de segundo tipo solo permite definiciones que utilizan el tipo COMPLEJO.
En C++, solo hay una sutil diferencia. Es un vestigio de C, en el que marca la diferencia.
El estándar del lenguaje C ( C89 §3.1.2.3 , C99 §6.2.3 y C11 §6.2.3 ) exige espacios de nombres separados para diferentes categorías de identificadores, incluidos identificadores de etiquetas (para struct/union/enum ) e identificadores ordinarios (para typedef y otros identificadores).
Si acabas de decir:
struct Foo { ... }; Foo x; obtendría un error del compilador, porque Foo solo está definido en el espacio de nombres de la etiqueta.
Tendrías que declararlo como:
struct Foo x ;
Cada vez que quieras referirte a Foo , siempre tendrás que llamarlo struct Foo . Esto se vuelve molesto rápidamente, por lo que puede agregar un typedef :
struct Foo { ... }; typedef struct Foo Foo; Ahora struct Foo (en el espacio de nombres de la etiqueta) y simplemente Foo (en el espacio de nombres del identificador ordinario) ambos se refieren a lo mismo, y puede declarar libremente objetos de tipo Foo sin la palabra clave struct .
El constructo:
typedef struct Foo { ... } Foo; es solo una abreviatura de la declaración y typedef .
Finalmente,
typedef struct { ... } Foo; declara una estructura anónima y crea un typedef para ella. Por lo tanto, con esta construcción, no tiene un nombre en el espacio de nombres de la etiqueta, solo un nombre en el espacio de nombres typedef. Esto significa que tampoco se puede declarar hacia adelante. Si desea realizar una declaración de reenvío, debe asignarle un nombre en el espacio de nombres de la etiqueta .
En C++, todas las declaraciones de clase struct/union/enum/ actúan como si estuvieran typedef implícitamente, siempre que el nombre no esté oculto por otra declaración con el mismo nombre.