Primero, ambas declaraciones son legales tanto en C como en C++. Sin embargo, en C, tienen una semántica ligeramente diferente. (En particular, la forma en que se refiere a la estructura más tarde varía).
El concepto clave para entender es que en C, las estructuras existen en un espacio de nombres separado. Todos los tipos incorporados, así como los typedefs existen en el espacio de nombres "predeterminado". Es decir, cuando escribo int
, el compilador solo comprueba este espacio de nombres "predeterminado". Si escribo "tagMyStruct" como en su ejemplo, el compilador también solo verifica este espacio de nombres. Pero dependiendo del tipo de declaración que use, la estructura puede no existir en ese espacio de nombres.
Las estructuras son diferentes y existen en un espacio de nombres separado. Así que si hago la siguiente declaración:
struct mystruct {};
puedo no simplemente se refieren a ella como MyStruct.En su lugar, tengo que especificar que quiero que el MyStruct que existe en el espacio de nombres estructura:
void foo(struct mystruct bar); // Declare a function which takes a mystruct as its parameter
que se pone un poco prolijo y torpe en el largo plazo. En su lugar, puede typedef en el espacio de nombres por defecto:
typedef struct mystruct mystruct; // From now on, 'mystruct' in the normal namespace is an alias for 'mystruct' in the struct namespace
y ahora, mi función puede ser declarada en la forma sencilla:
void foo(mystruct bar);
Así que su primer ejemplo simplemente se fusiona estos dos pasos juntos: DECLARE una estructura, y poner un alias en el espacio de nombres regular. Y, por supuesto, dado que estamos volviendo a escribirlo de todos modos, no necesitamos el nombre "original", por lo que podemos hacer que la estructura sea anónima. Así que después de su declaración
typedef struct { int i; double d; } tagMyStruct;
tenemos una estructura sin nombre, que ha sido typedef'ed a 'tagMyStruct' en el espacio de nombres predeterminado.
Eso es como C lo trata. Ambos tipos de declaraciones son válidas, pero una no crea el alias en el espacio de nombres "predeterminado", por lo que debe usar la palabra clave struct cada vez que se refiera al tipo.
En C++, el espacio de nombres estructura separada no existe, por lo que significa la misma cosa. (pero se prefiere la versión más corta).
Editar Para que quede claro, no, C no tiene espacios de nombres. No en el sentido habitual. C simplemente coloca los identificadores en uno de los dos espacios de nombres predefinidos. Los nombres de las estructuras (y las enumeraciones, según recuerdo) se colocan en una, y todos los demás identificadores en otra. Técnicamente, estos son espacios de nombres porque son "contenedores" separados en los que se colocan los nombres para evitar conflictos, pero ciertamente no son espacios de nombres en el sentido C++/C#.
buena explicación – Eclipse
Así C _does_ tienen espacios de nombres! :) Gracias, eso aclara muchas cosas. – xtofl
xtofl: No, en realidad no. No en el sentido C++. las estructuras y los tipos incorporados existen en espacios de nombres separados, pero más allá de eso, no. No puede declarar nuevos espacios de nombres, o cualquier otra cosa que espere. Este es un caso especial. Es probablemente una mala idea pensar en ello como "C tiene espacios de nombres";) – jalf