Trollhorn
Trollhorn

Reputation: 229

C structs don't define types?

I've just started learning C with a professional Java background and some (if no too much) C++ knowledge, and I was astonished that this doesn't work in C:

struct Point {
    int x;
    int y;
};

Point p;

p.x = 0;
p.y = 0;

It seems that I have to declare p using struct Point as the type or using a typedef. Does this code works in C99? Or is this a "C++ thing"?

Upvotes: 4

Views: 3003

Answers (10)

Armin Ronacher
Armin Ronacher

Reputation: 32533

Structs are not types. You can create a point from a struct as follows:

struct Point p;
p.x = 0;
p.y = 0;

If you want to use a struct as a type, you have to typedef it. This works in both C and C++:

typedef struct _point {
    int x;
    int y;
} Point;

Always give your struct a name though, if you have to forward declare it to be able to have pointers to a struct of the same type or circular dependencies.

Upvotes: 1

DigitalRoss
DigitalRoss

Reputation: 146053

So...

Point           a tag
struct Point    a type

typedef struct {
    . . .
} Point_t;

Point_t         a type

I often see a why? written between the lines. After all, it does seem perfectly reasonable to just say Point x;, so why can't you?

As it happens, early implementations of C established a separate name space for tags vs other identifiers.There are actually 4 name spaces1. Once the language was defined this way, it was then not possible to allow the struct tag to be used as a type because then all existing code with name collisions between ordinary identifiers and tags would be suddenly in error.


1. The 4 name spaces are:
-- label names (disambiguated by the syntax of the label declaration and use);
-- the tags of structures, unions, and enumerations (disambiguated by following any) of the keywords struct, union, or enum);
-- the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
-- all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants)

Upvotes: 2

Pete Kirkham
Pete Kirkham

Reputation: 49311

In C there is no confusion between

struct Point {
    int x;
    int y;
};

and

union Point {
    int x;
    int y;
};

which are two different types called struct Point and union Point respectively.

The C99 standard section 6.7.2.1 states:

6 Structure and union specifiers have the same form. The keywords struct and union indicate that the type being specified is, respectively, a structure type or a union type.

7 The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.

So it most unequivocally declares a type. The syntax for type names in C is given in sections 6.7.6 and includes the specifier-qualifier-list from 6.7.2, which takes the form of struct-or-union identifier.

Does this code works in C99? Or is this a "C++ thing"?

No, C99 does not decide to promote structure types over enum types and union types with the same name. It is a "C++ thing", as struct and classes are mostly the same thing in C++, and classes are important to C++.

Upvotes: 4

user50049
user50049

Reputation:

You first need to make Point a type like :

typedef struct Point {
    int x;
    int y;
} Point;

This allows you to use Point as a type, or struct Point

I.e:

Point *p;

sizeof(struct Point);

Some people prefer to make the name of the structure different from the type being created, such as:

typedef struct _point {
       ...
} Point;

You'll run into both. The last example tells me that I should not use struct _point, its not meant to be exposed except as the type Point.

Upvotes: 0

Andomar
Andomar

Reputation: 238068

In C, structs can have two kinds of names: a tag name, and a type name. A tag name can only be used if it's prefixed with struct, like:

struct mytag { int a; }
struct mytag mystruct;

A typedef allows you to define both a tag name and a type name. The type name can be used without a struct prefix:

typedef struct mytag { int a; } mytype;
mytype mystruct; // No struct required

Upvotes: 1

D.Shawley
D.Shawley

Reputation: 59553

struct Point is the type just like union Foo would be a type. You can use typedef to alias it to another name - typedef struct Point Point;.

Upvotes: 4

Remo.D
Remo.D

Reputation: 16512

No, a struct do not define a new type. What you need is:

typedef struct {
   int x; int y;
} Point;

Now Point is new type you can use:

Point p;
p.x = 0; p.y = 0;

Upvotes: 5

Robert Gamble
Robert Gamble

Reputation: 109012

It doesn't work in C99, it is a C++ thing. You have to either say struct Point or use a typedef in C.

Upvotes: 1

Mikael Auno
Mikael Auno

Reputation: 9060

As far as I know, it shouldn't work without a typedef in C99 either (as this is simply the way C works), but it does work in C++ as a struct in C++ is just a class with all members public by default.

Upvotes: 8

Nathan Fellman
Nathan Fellman

Reputation: 127428

That's the way C works. In C you have to say:

typedef struct Point {
    int x;
    int y;
} Point;

And then you'll have a type called Point that does what you want.

In C++ it's enough to define it the way you did.

Upvotes: 0

Related Questions