60

I've always been a little confused about what's going on here:

#include <stdio.h>

int main() {  
    timeval tv;
    tv.tv_sec = 1;

    for (;;) {
        select(0, 0, 0, 0, &tv);
        printf("%s\n", "Hello World!");
    }
}

Sorry if that doesn't compile, just wrote it as a quick example.

Code like this won't compile under gcc unless I add the keyword struct prior to the use of the struct timeval. g++ on the other hand handles it fine as is.

Is this a difference between how C and C++ handle structures or is it just a difference in the compilers? (I'm very C++ oriented, and the use of struct in C on lines like this has always somewhat baffled me).

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • 12
    I like to think of C having a "typedef namespace" and a "struct namespace". If a struct isn't typedef'd, you'll need to explicitly put the "struct" before it in order to "resolve" its "namespace". You can imagine that C++ automatically chucks all structs into the "typedef namespace". This is of course not really what's going on, but I find this mental model useful. – Rooke Dec 07 '11 at 21:56
  • C needs the keyword because that's its syntax. I'm not sure what's being asked here. Are you wondering about the design rationale? – Maxpm Dec 07 '11 at 23:14
  • @Rooke, for additional confusion, the "typedef" namespace is actually the object namespace; `typedef` is a storage class like `static`, `extern` and `auto`, so a typedef declaration is syntactically the same as an object declaration. – Simon Richter Dec 08 '11 at 07:49
  • 3
    @Rooke, that's pretty much exactly what's going on, C struct tags are in their own namespace, and .. what Simon said about typedef namespace. In original K+R C, all names of struct members were in a *common* namespace - this is why the ancient system structs like 'struct stat' all have prefixes ( st_dev, st_ino, st_mode ...) to avoid collisions with members of other structs. Each such name was associated with a type and offset, not what struct it was in. So the -> operator didn't care what pointer type was on the left. That was fixed pretty early on though. – greggo Feb 21 '15 at 21:21

6 Answers6

98

Syntactically both treat struct almost the same. Only C++ has added an extra rule that allows to omit the struct (and class) keyword if there is no ambiguity.

If there is ambiguity, also C++ requires the struct keyword in some places. A notorious example is stat on POSIX systems where there is a struct stat and a function stat.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 2
    There is also an example or `struct sigaction` and `int sigaction(...)` method for handling signals in Linux (from `signal.h`) where you need to to `struct` keyword if you want to use the `struct` – Patryk Mar 23 '16 at 14:39
  • I'd like to add, struct is basically the same as class, except struct's default member export is 'public' but class's is 'private'. – matiu Apr 08 '16 at 23:19
13

Consider the original idea of C++ (or, when it was just an idea, "C with classes"), that of an OO-oriented language that was compatible with C to the point where most valid C programs were also valid C++ programs.

C++ built its class model by starting with C's struct and adding some further functionality:

  1. Inheritance (though you can come close in C with having the first member of a struct the struct you want to "inherit" from).
  2. Information hiding (through public, private etc)
  3. Member methods (which were originally turned by macros into C code outside the struct with an added this parameter - many implementations are still similar in practice).

At this point there were two problems. The first is that the default access had to be public, since C has no information hiding and therefore from a C++ perspective has everything public. For good OO one should default to private. This was solved by adding class which is pretty much identical to struct except for the default is private rather than public.

The other is that this OO perspective should have timeval or any other class/struct on the same "footing" as int or char, rather than constantly annotated in the code as special. This was solved by relaxing the rule that one must place struct (or class) before the name of the type in declaring a variable of that type. Hence struct timeval tv can become timeval tv.

This then influenced later C-syntax OO languages, like Java and C# to the point where, for example, only the shorter form (timeval tv) would be valid syntax in C#.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
11

I would say it's a design decision of both languages.

Structs in C are just structured records and have different usage then built-in type.

C++ has ctors and operator overloads and so they act as types.

struct foo x;         // create a structure of pattern foo
typedef foo foo_type; // "define" a type
foo_type x;           // create an instance of type foo_type

C++:

foo x; // create an instance of type foo

As a side-note, struct foo is still allowed in C++. struct foo is easier to parse then typedef'dfoo as the name-lookup is simpler.

Pubby
  • 51,882
  • 13
  • 139
  • 180
8

It's just how C looks like. Therefore, the following patterns is pretty common in C:

typedef struct YourStructure
{
   int x;
   // more fields
} YourStructure;

Then you can reference it the same way like in C++.

Krizz
  • 11,362
  • 1
  • 30
  • 43
7

It's simply a difference in the languages. C++ is more permissive in its struct syntax.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 4
    Permissive is a very unfitting word. – Šimon Tóth Dec 07 '11 at 21:29
  • 3
    Because this is about namespaces not about permissiveness. – Šimon Tóth Dec 07 '11 at 21:32
  • @Let_Me_Be What should I say? – David Heffernan Dec 07 '11 at 21:33
  • That C++ have less sorts of namespaces than C (which have different spaces for variables, labels, struct names, ...) – Basile Starynkevitch Dec 07 '11 at 21:35
  • 2
    @Basile From the coder's perspective, C++ struct syntax is more forgiving. That's the most important point. I doubt the motivation for the variation was related to namespaces. The motivation was surely to make life easier and simpler for coders. – David Heffernan Dec 07 '11 at 21:44
  • 2
    @BasileStarynkevitch, C++ has inherited the same "types" of namespaces (in the sense of C) from C. It only has an extra rule to interpret identifiers in the tag namespace as types. See my answer for an example. – Jens Gustedt Dec 07 '11 at 21:47
  • I used the namespace word in the generic sense (like you would say that Scheme has only one namespace, but Common Lisp has two), not in the sense of the `namespace` keyword of C++ – Basile Starynkevitch Dec 07 '11 at 21:48
  • 1
    @BasileStarynkevitch I know what you mean when you talk about namespace. I just think that's an implementation detail that's not particularly illuminating from the perspective of the person asking the question. – David Heffernan Dec 07 '11 at 21:49
4

The way C does it came first, of course. Structs and classes in C++ are nearly identical, and it would have been very inconvenient to require class with every class variable so it was simplified for both.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622