7

Though I rarely write C code, I often see it (mostly due to books in my field having it as sort of reference language for algorithm examples) and something has been bugging me for a while about the way variables/parameters are declared. The best example would be this List with a twist example, about a particular implementation of Linked List used in Linux kernel (sorry, I had a link to a blog post originally, but apparently the blog post has been deleted, I copied code from my browser's cache).

struct blog {
  ...
  struct ls posts;
};

struct post {
  ...
  struct ls blog_posts;
};

void delete_blog(struct blog *blog) {
  ...
  struct post *p;
  ls_for_each(&blog->posts, p, blog_posts) {
    free(p);
  }
  free(blog);
}

What bugs me is the fact that they keep repeating the keyword struct everywhere. I mean things like ls, blog, post are declared as structs, so what is the point of saying it is a struct every time you declare a variable or a function parameter of that type? What does this tell the compiler that it can't infer from the fact that the thing you are instantiated has been defined as a struct?

Alex K
  • 10,835
  • 8
  • 29
  • 34
  • If you are coming from a C++ background, You are used to using structures without the `struct` keyword appearing before it everywhere.But in C the language syntax needs the keyword to be pre-pended everywhere.It is indeed a pain but that is how the language syntax was designed. – Alok Save Nov 05 '11 at 13:09
  • see http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions/1675507#1675507 – Christoph Nov 05 '11 at 14:04

5 Answers5

8

Well, it's because if there isn't a typedef, that's the only way to refer to the struct.

In C, if you have:

struct thing {
  // stuff here
};

and you want to have a variable of that type, you need to either:

  • use struct thing as the type specifier
  • make a typedef like typedef struct thing thing_t; and use thing_t as the type specifier.

(C++ is different in this respect.)

Mat
  • 202,337
  • 40
  • 393
  • 406
  • Yes, I do come from C++ background, and I just didn't think a behavior of a fairly fundamental keyword like this would be different between the two. – Alex K Nov 05 '11 at 13:15
  • 1
    Check out [Constructs that behave differently in C and C++](http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Constructs_that_behave_differently_in_C_and_C.2B.2B). – Mat Nov 05 '11 at 13:18
  • @AlexK: It's not really different. It only has the added convenience of implicitly adding a `typedef` of the same name, which is what many C programmers do anyway. There are other, much more significant differences (casting void pointers anyone?). –  Nov 05 '11 at 13:19
  • I guess what really threw me off (and ingrained the idea that struct in C is just like C++) is that editors highlight 'struct' and 'thing' (from your example) with 2 different colors. Should be the whole thing with the color of identifier. I know it's lame excuse, but I'm big on visual cues. – Alex K Nov 05 '11 at 13:24
  • "struct" is a keyword. "thing" is an identifier. That's why they are different colors. – Raymond Chen Nov 05 '11 at 13:27
  • 1
    @delnan: Actually, C++ does not implicitly add a `typedef` of the same name, for reasons of compatibility with C, which lets you define a struct and a function having the same name. What C++ does, is look for structs as well as typedefs when resolving an identifier. Subtle difference, but you trip over it if you define a struct and a function of the same name in C++ - the name then refers to the function unless you precede it with the `struct` keyword, exactly the same as in C. – Steve Jessop Nov 05 '11 at 17:07
  • 1
    Though I gotta admit, while this explains why all programs do it (so my original question is answered), none of this explains why the compiler can't infer it with 100% certainty. – Alex K Nov 05 '11 at 21:26
  • @Alex: if the language was defined differently, then a `struct` definition could introduce a name for a type in exactly the same way that a `typedef` does, and there would be no need to precede such typenames with `struct`. The reason the language isn't defined that way is pretty ancient, I think, it might even be fundamentally arbitrary or an accident. After that, though, compatibility takes over. Nobody has ever wanted to break C code that has a function and a struct of the same name, or code like `struct foo {}; struct bar {}; typedef bar foo;` such that `foo f;` != `struct foo f;`. – Steve Jessop Nov 06 '11 at 19:16
7

struct tags are in a different namespace than usual identifiers. So the struct keyword is necessary to specify that. A famous example is in POSIX where you have a struct stat and a function stat.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
3

It is just the way the syntax is...

C is a quite old language, and it purposely created a syntax which differentiated between the typed which could be represented directly by machine instructions and those which were more complex and spanned several memory locations.

"Typedef" was added to the language to allow the creation of shorter names which didn't included the struct, however the full struct syntax is used - and specifically is used in historical context where the original definition of a system structure is defined as "struct" without a corresponding typedef short form.

As comparison C++ which is a much later language, allows a class/struct to be referred to by just the class/struct name regardless of whether it was defined with a typedef.

So as questions goes, the answer is that it just is like that because it is...

EDIT: Just looking at your example code, there is one notable case where struct adds something to the compiler behavior -- in most cases a type has to be defined before it can be used in a another declaration -- except for when you refer to a struct sometype* (i.e. a pointer to a struct) in which case the compiler is happy to have the sometype defined after the use.

so

struct post {
   struct post *nextpost;
   struct post *prevpost;
   ...
};

becomes possible, as post is not defined until the closing bracket of the struct.

Soren
  • 14,402
  • 4
  • 41
  • 67
1

struct is part of the type declaration.

If a function takes an argument (/parameter), then the type of that argument must be declared. How could you declare that that argument is a struct if you cannot use the word struct ?

Erwin Smout
  • 18,113
  • 4
  • 33
  • 52
1

Many modern C libraries are systematically typedef-ing their struct and use some naming convention. For example gtk/gtkalignment.h has:

typedef struct _GtkAlignment              GtkAlignment;
typedef struct _GtkAlignmentPrivate       GtkAlignmentPrivate;
typedef struct _GtkAlignmentClass         GtkAlignmentClass;

My own habit is to name foo_st the struct and foo_t the type, so I often code

typedef struct foo_st foo_t;

And I would use union foo_un if it where a union.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547