reservada - typedef struct uso
typedef una estructura antes de que sea declarada (7)
Bajo ciertas circunstancias, es válido usar un tipo de struct ...
antes de que se declare. Es un llamado "tipo incompleto" entonces.
Por ejemplo, es válido declarar una variable como un puntero a una estructura "incompleta", así como (como puede ver) un typedef
.
No soy un principiante, estoy muy familiarizado con el siguiente lenguaje:
typedef struct Foo_ Foo;// I know typedef struct Foo Foo is fine, I''m just trying to make it clearer
struct Foo_
{
int value;
Foo *link;
};
Simplemente me siento confundido de repente, porque entiendo que no está permitido usar un nombre (identificador) antes de que se declare. Pero en la declaración typedef struct Foo_ Foo
, el identificador Foo_
aún no existe! ¿Cómo es que el compilador permite que esto suceda? ¿Alguien, por favor, arrojaría algo de luz sobre esto, me explicaría cuál es la justificación de este tipo de sintaxis?
Cita de Wikipedia: el propósito de typedef
es asignar nombres alternativos a los tipos EXISTENTES.
---> 8 ---
Gracias a todos por la información tan útil.
Esto está completamente bien. El primer uso de la etiqueta struct
como la suya es una declaración hacia adelante del tipo de struct
.
Tenga en cuenta que su uso de _Foo
no es conforme. Los identificadores con el guión bajo y la letra mayúscula siguiente están reservados. No hagas eso. El subrayado final estaría bien.
Esto está cubierto en 6.7.2.3p8:
6.7.2.3 Etiquetas
Semántica
[...]8 - Si un especificador de tipo de la forma struct-or-union identifier ocurre de otra manera que no sea como [una definición de struct-or-union] o [una declaración de struct-or-union], y ninguna otra declaración del identificador como una etiqueta es visible, luego declara una estructura incompleta o tipo de unión, y declara el identificador como la etiqueta de ese tipo.
El especificador de tipo struct Foo
en typedef struct Foo Foo
no se encuentra en una definición ( struct Foo {...};
) o en una declaración ( struct Foo;
), por lo que se incluye en 6.7.2.3p8.
Tenga en cuenta que no hay nada especial sobre typedef
; También podrías, por ejemplo, escribir.
struct A { struct Foo *p; };
y no se requiere que una definición o declaración previa sea visible.
Sin embargo, en una declaración de función o definición:
void foo(struct Foo *p);
Si la struct Foo
no se ha declarado previamente, el alcance de la declaración solo será la declaración o definición de la función, y no será compatible con el tipo con ninguna declaración o definición posterior de Foo
.
Se llama declarar hacia adelante. La declaración hacia adelante le permite usar su nombre en el contexto donde se permite un tipo incompleto.
El compilador "verá" la etiqueta typedef y la almacenará hasta que se encuentre el tipo, por lo que siempre que tenga el tipo declarado allí después de typedef, pero antes de cualquier uso, está bien.
typedef
se utiliza para crear un alias para un tipo. Pero ese tipo no necesariamente existe cuando está tipificado.
Por ejemplo,
si solo haces
struct Foo;
y nunca define la struct Foo
en ningún lugar del programa, entonces aún se compilará. El compilador asumirá que está definido en algún lugar y continuará. Solo si lo usa sin definir la estructura, se producirá un error.
Es el caso similar con typedef
también.
Una declaración typedef le permite definir sus propios identificadores que se pueden usar en lugar de especificadores de tipo como int, float y double. Una declaración typedef no reserva almacenamiento.
para obtener más información http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc03typdef.htm
ISO c99 : 6.2.1 Scopes of identifiers
7
Las etiquetas de estructura, unión y enumeración tienen un alcance que comienza justo después de la aparición de la etiqueta en un especificador de tipo que declara la etiqueta.
typedef struct _Foo Foo; // You can do this because it''s just the typedef the new type
struct _Foo *myfoo ; // It''s pointer to struct _Foo (an incomplete type)
//but make sure before using myfoo->value
// struct definition should be available
struct _Foo MyFoo; // It''s definition of MyFoo but don''t forget
// to give the definition of struct _Foo (gcc extension).
struct _Foo; // forward declaration
struct _Foo // It''s the definition
{
int value;
Foo *link;
};
Simplemente, en cuanto a las functions
, forward declaration
o typedef
antes de la definición real de la función, así que también podemos hacerlo con struct
.
void func(int );
typedef void (*func_t)(int);
void func(int x)
{
//actual definition
}