Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typedef a struct before it's declared

Tags:

c

typedef

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.

like image 441
Need4Steed Avatar asked Nov 29 '12 12:11

Need4Steed


People also ask

Should you typedef a struct?

PLEASE don't typedef structs in C, it needlessly pollutes the global namespace which is typically very polluted already in large C programs. Also, typedef'd structs without a tag name are a major cause of needless imposition of ordering relationships among header files.

What is a typedef struct?

You can use typedef to give a name to your user defined data types as well. For example, you can use typedef with structure to define a new data type and then use that data type to define structure variables directly as follows −

Is typedef a declaration or definition?

A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared.


3 Answers

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.

like image 136
Jens Gustedt Avatar answered Sep 27 '22 22:09

Jens Gustedt


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.

like image 20
ecatmur Avatar answered Sep 27 '22 22:09

ecatmur


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
}
like image 20
Omkant Avatar answered Sep 27 '22 21:09

Omkant