views:

1308

answers:

9

I'm a beginner with C programming, but I was wondering what the difference was between the using typedef when defining a structure versus not using typedef. It seems to my like there's really no difference, they accomplish the same.

struct myStruct{
    int one;
    int two;
};

vs.

typedef struct{
    int one;
    int two;
}myStruct;
+3  A: 

The typedef, as it is with other constructs, is used to give a data type a new name. In this case it is mostly done in order to make the code cleaner:

struct myStruct blah;

vs.

myStruct blah;
RC
+1  A: 

In strict ANSI 89 C these are very different. The first will only define a type called struct myStruct. It would not be legal to refer to it by the simple name myStruct. The latter though only defines the type myStruct.

These days though, most compilers and C++, auto do the typedef under the hood so the resulting definition is not different.

JaredPar
In C++ (and I bet that current C compilers behave the same), the typedef is not performed under the hood. The typedef defines the identifier as an alias to the struct type, so after the typedef there is a 'struct X' and a type 'X'. What C++ determines is that when searching for a type symbol 'X' the compiler will first search within the global symbol table (functions, typedefs...) and if the identifiers is not found it will search within the struct symbol table as if 'struct' was provided by the programmer. In most code there will be no difference, but in some instances there will (collisions)
David Rodríguez - dribeas
+7  A: 

In C (not C++), you have to declare struct variables like:

struct myStruct myVariable;

In order to be able to use myStruct myVariable; instead, you can typedef the struct:

typedef struct myStruct someStruct;
someStruct myVariable;

You can combine struct definition and typedefs it in a single statement which declares an anonymous struct and typedefs it.

typedef struct { ... } myStruct;
Mehrdad Afshari
The last block of code is not equivalent to the previous code. In the last line you are defining a type alias 'myStruct' into an unnamed struct. There are (very) subtle difference among the two versions.
David Rodríguez - dribeas
dribeas: I covered this subtle difference in the sentence "...a single statement which declares **an anonymous struct** and..."
Mehrdad Afshari
True, I seem to have skipped that part :)
David Rodríguez - dribeas
+2  A: 

The difference comes in when you use the struct.

The first way you have to do:

struct myStruct aName;

The second way allows you to remove the keyword struct.

myStruct aName;
jjnguy
+2  A: 

If you use struct without typedef, you'll always have tor write

struct mystruct myvar;

It's illegal tor write

mystruct myvar;

If you use the typedef you don't need the struct prefix anymore.

RED SOFT ADAIR
+1  A: 

With the latter example you omit the struct keyword when using the structure. So everywhere in your code, you can write :

myStruct a;

instead of

struct myStruct a;

This save some typing, and might be more readable, but this is a matter of taste

shodanex
+20  A: 

The common idiom is using both: typedef struct X { int x; } X;

They are different definitions. To make the discussion clearer I will split the sentence:

struct S { int x; };
typedef struct S S;

In the first line you are defining the identifier S within the struct name space (not in the C++ sense). You can use it and define variables or function arguments of the newly defined type by defining the type of the argument as struct S:

void f( struct S argument ); // struct is required here

The second line adds a type alias S in the global name space and thus allows you to just write:

void f( S argument ); // struct keyword no longer needed

Note that since both identifier name spaces are different, defining S both in the structs and global spaces is not an error, as it is not redefining the same identifier, but rather creating a different identifier in a different place.

To make the difference clearer:

typedef struct S { int x; } T;
void S() {} // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'

You can define a function with the same name of the struct as the identifiers are kept in different spaces, but you cannot define a function with the same name as a typedef as those identifiers collide.

In C++, it is slightly different as the rules to locate a symbol have changed subtly. C++ still keeps the two different identifier spaces, but unlike in C, when you only define the symbol within the class identifier space, you are not required to provide the struct/class keyword:

 // C++
 struct S { int x; }; // S defined as a class
 void f( S a ); // correct: struct is optional

What changes are the search rules, not where the identifiers are defined. The compiler will search the global identifier table and after S has not been found it will search for S within the class identifiers.

The code presented before behaves in the same way:

typedef struct S { int x; } T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'

After the definition of the S function in the second line, the struct S cannot be resolved automatically by the compiler, and to create an object or define an argument of that type you must fall back to including the struct keyword:

// previous code here...
int main() {
    S(); 
    struct S s;
}
David Rodríguez - dribeas
+4  A: 

In C, type tags are mandatory, ie by default, you always have to prefix type names with the appropriate keyword struct, union or enum.

You can get rid of the tag by using a typedef, which is a form of information hiding as the actual type of an object is no longer visible when declaring it.

It is therefore recommended (eg in the Linux kernel coding style guide) to only do this when you actually want to hide this information and not just to safe a few keystrokes.

An example of when you should use a typedef would be an opaque type which is only ever used with corresponding accessor functions/macros.

Christoph
Linux kernel coding style guide for reference: http://www.kernel.org/doc/Documentation/CodingStyle
Tomek Szpakowicz
+1  A: 

Another difference not pointed out is that giving the struct a name (i.e. struct myStruct) also enables you to provide forward declarations of the struct. So in some other file, you could write:

struct myStruct;
void doit(struct myStruct *ptr);

without having to have access to the definition. What I recommend is you combine your two examples:

typedef struct myStruct{
    int one;
    int two;
}myStruct;

This gives you the convenience of the more concise typedef name but still allows you to use the full struct name if you need.

R Samuel Klatchko
+1: none of the other answers deal with the forward declaration issue that you bring.
David Rodríguez - dribeas