Reputation: 2180
I'm not a beginner, I'm very familiar with the following idiom:
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;
};
I'm just suddenly feel confused, because my understanding is that it's not allowed to use a name(identifier) before it's declared. But in the declaration typedef struct Foo_ Foo
, the identifier Foo_
does not yet exist! How come the compiler permit this happen? Would anybody please shed some light on this, explain to me what's the justification for this kind of syntax?
Wikipedia quote : The purpose of typedef
is to assign alternative names to EXISTING types.
--- >8 ---
Thank you all guys for so much helpful information.
Upvotes: 34
Views: 12836
Reputation: 9204
ISO c99 : 6.2.1 Scopes of identifiers
7
Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag.
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;
};
Simply as for functions
we do forward declaration
or typedef
before actual definition of function , So we can do it with struct
also.
void func(int );
typedef void (*func_t)(int);
void func(int x)
{
//actual definition
}
Upvotes: 4
Reputation: 157354
This is covered in 6.7.2.3p8:
6.7.2.3 Tags
Semantics
[...]8 - If a type specifier of the form struct-or-union identifier occurs other than as [a struct-or-union definition] or [a struct-or-union declaration], and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type.
The type specifier struct Foo
in typedef struct Foo Foo
is not in a definition (struct Foo {...};
) or a declaration (struct Foo;
) so it falls under 6.7.2.3p8.
Note that there's nothing special about a typedef
; you could also e.g. write
struct A { struct Foo *p; };
and a previous definition or declaration is not required to be visible.
However, in a function declaration or definition:
void foo(struct Foo *p);
if struct Foo
is not previously declared then the scope of the declaration will just be the function declaration or definition, and it will not be type-compatible with any subsequent declaration or definition of Foo
.
Upvotes: 15
Reputation: 121387
typedef
is used to create an alias for a type. But that type doesn't necessarily exist when typedef'ed.
For example,
if you just do:
struct Foo;
and you never define the struct Foo
anywhere in the program, then it'll still compile.
Compiler would assume it's defined somewhere and continue. Only if you use it without defining the struct, an error will occur.
It's the similar case with typedef
as well.
Upvotes: 3
Reputation: 49403
It's called forward declaring. The forward declaration allows you to use its name in context where an incomplete type is allowed.
The compiler will "see" the typedef tag, and store it away until the type is found, so as long as you have the type declared in there after the typedef, but before any usage, it's fine.
Upvotes: 2
Reputation: 91029
Under certain circumstances, it is valid to use a struct ...
type before it is declared. It is a so-called "incomplete type" then.
For example, it is valid to declare a variable as a pointer to an "incomplete" struct, as well as (as you can see) a typedef
.
Upvotes: 1
Reputation: 78903
This is completely fine. The first use of struct
tag like yours is a forward declaration of the struct
type.
Beware though that your usage of _Foo
is not conforming. Identifiers with leading underscore and following capital letter are reserved. Don't do that. Trailing underscore would be ok.
Upvotes: 34
Reputation: 1823
A typedef declaration lets you define your own identifiers that can be used in place of type specifiers such as int, float, and double. A typedef declaration does not reserve storage.
Upvotes: -2