It is the difference between C and C++.
In both languages there is an older “name space” (note the space in the name) that refers to how the compiler classifies names. In C, names following the
struct
keyword are in their own lookup table, so they cannot be confused with any other name in code. As a result, if you wish to use a structure type name in C you must specify that it is a struct:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
// C
struct point
{
double x, y;
};
struct point add( struct point a, struct point b )
{
struct point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
return c;
}
|
The
typedef
operator makes a type alias — meaning you can create new type names out of other types. C programmers use it to make the above syntax easier to digest:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// C
typedef struct
{
double x, y;
}
point;
point add( point a, point b )
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
return c;
}
|
In other words, the (unnamed) structure is now given an alias name: “point”. We can use that alias for the structure any time now.
In C++, the old ‘struct’ name space still exists, but all names are automatically added to
both the struct name space and the general type name space. Hence, no
typedef
is required:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
C++
struct point
{
double x, y;
};
point add( point a, point b )
{
point c;
c.x = a.x + b.x;
c.y = a.y + b.y;
return c;
}
|
As an addendum to your question, there are times where it still makes a difference, particularly if you intend your code to compile both in C and C++: use the C method.
Also, whenever a C struct is self-referential, you must use the “struct” syntax until the typedef-ed name is declared. Perhaps the most common use for this is linked lists (and opaque structs, which is a concept you can ignore for now):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
#include <stdio.h>
#include <stdlib.h>
struct list_tag
{
int x;
struct list_tag* next;
};
typedef struct list_tag list;
list* cons( int x, list* next )
{
list* car = (list*)malloc( sizeof(list) );
car->x = x;
car->next = next;
return car;
}
void print( list* xs )
{
while (xs)
{
printf( "%d ", xs->x );
xs = xs->next;
}
printf( "\n" );
}
int main()
{
list* xs = cons( 2, cons( 3, cons( 5, cons( 7, NULL ) ) ) );
print( xs );
}
|
Here we created a linked list containing the first few prime numbers, then printed it by following the
next pointer until we hit the end (
NULL).
Hope this helps.