Gireesh Kumar Gireesh Kumar - 2 months ago 7
C Question

Structure in c K&R page no.129

I am learning c from K&R and have reached page no.1129 where the following code is listed.

struct rect {
struct point pt1;
struct point pt2;
};


What it does mean?

Answer

Short Version

struct rect {
  struct point pt1;
  struct point pt2;
};

creates a new structure type named struct rect, consisting of the members pt1 and pt2, each of which has type struct point.

The struct keyword is part of the type name, and must be present when you declare pt1 and pt2.

Not So Short Version

In C, most type names are reserved words – int, float, char, etc. – and cannot be used for any other purpose; that is, you can't name a variable or a function int.

However, the tag name for a struct type (point and rect in the code above) is not a reserved word; it's an identifer that could also be used as a variable or function name, or in other contexts. For the C compiler to know you're talking about the point type and not a point variable, you need to include the struct keyword.

C has four different name spaces; that is, four different contexts in which the same identifier can be used without causing a conflict:

  • Label names;
  • Tag names for struct, union, and enum types;
  • Member names for structures and unions;
  • Ordinary identifiers (variable names, function names, typedef names, enumeration constants).

Thus, the following code is legal (if a really bad idea):

      struct foo { int foo; int bar; } foo;
      ...
      goto foo;
      ...
foo:  printf( "foo.foo = %d\n", foo.foo );

The compiler disambiguates (distinguishes between) the different uses of foo as follows:

  • The label foo is disambiguated by the goto keyword and trailing :;
  • The tag name foo is disambiguated by the struct keyword;
  • The member name foo is disambiguated by the . member selection operator;
  • And the ordinary identifier foo is disambiguated by not fitting any of the previous cases.

Thus, if you want to refer to the types struct point and struct rect, the struct keyword must be present; otherwise the compiler will think you're talking about a variable named point or rect and get confused.

You can create a typedef name as an alias or synonym of struct point:

struct point { ... };
typedef struct point point;

Now the identifier point is an alias for the type struct point, allowing you to declare points as

point pt1, pt2;

Note that in the ordinary identifier namespace, you cannot do something this:

typedef struct point { ... } point;
point point;

because in that namespace, point may either be a typedef name or a variable name, but not both.

However, gcc is letting me get away with the following:

typedef struct point { ... } point;
typedef struct rect { point point; } rect;

because in this case, the second instance of point in the rect type definition is in the member name namespace, not the ordinary identifier namespace.

Comments