6
#include <stdio.h>
#include <string.h>

const int NAMELEN=30;

const int MAXCLASSSIZE=10;

typedef struct StudentRec {
    char lastname[NAMELEN];
    char firstname[NAMELEN];
    long int ID;
    int finalmark;
}Student;

I'm new to coding..and I have a question about why there is Student; after the bracket.. is it a format that we have to follow.

swegi
  • 4,046
  • 1
  • 26
  • 45
bloomy
  • 81
  • 1
  • 2
  • 1
    That's C, not C++. Are you sure you're referring to the right language? – Billy ONeal Apr 13 '10 at 14:54
  • 5
    C or C++, no difference in this example. Look up typedef on google or in your books. – Gregor Brandt Apr 13 '10 at 14:55
  • 6
    @gbrandt: Yes, but there's no reason to declare a struct that way in C++. – Billy ONeal Apr 13 '10 at 14:56
  • Please rephrase title as a question. Instead of "I have a question about C++" a better question would be: "Why does a struct have a name after the final brace in C++?" Even sometimes "Why do I need to put something after the squiggly bracket in C++?" – Armstrongest Apr 13 '10 at 14:57
  • 2
    @Billly ONeal: Correct, but it's still valid C++. I see this done a lot, presumably by people who carry over the habit from C. – Fred Larson Apr 13 '10 at 15:00
  • 2
    Are you people incapable of reading the actual question "is it a format that we have to follow?" – John Dibling Apr 13 '10 at 15:02
  • @gbrandt: There is a difference. In C++, the `struct` tag is in the same namespace as all other identifiers. – sbi Apr 13 '10 at 15:39
  • @John Dibling: Doesn't "unnecessary in C++" answer that question? – Fred Larson Apr 13 '10 at 15:45
  • 1
    @sbi: In fact the struct tags are in a different namespace in C++ as well. The difference is that the compiler will also look inside the struct tag namespaces when confronted with an identifier (unlike in C, where you have to request it with the `struct` keyword). For a longer explanation: http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions/1675446#1675446 – David Rodríguez - dribeas Apr 13 '10 at 17:01
  • @David: Thanks, I just learned something new. – sbi Apr 13 '10 at 22:08

5 Answers5

17

you are confusing two things. In C you can define a struct like this:

struct foo {
    int a, b;
};

Then to use one you have to do this:

struct foo myFoo;

This is really wordy, so they had this brilliant idea of using typedef to make a new type. I can do something like this:

typedef int myInt;

and then use it:

myInt x;

So what you're doing is declaring that there is a new type, Student, which is equivalent to a struct StudentRec. By convention, many people use the same name for the typedef as for the struct - it is legal:

typedef struct foo { int a, b; } foo;
plinth
  • 48,267
  • 11
  • 78
  • 120
13

This is creating a typename "Student" to mean the struct. Using typedef for this purpose is unnecessary in C++. It could be defined like this:

struct Student {
    char lastname[NAMELEN];
    char firstname[NAMELEN];
    long int ID;
    int finalmark;
};
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 1
    In most cases it is unnecessary, but there are slight differences between the definition of the struct and typedef-ing it. The identifiers reside in different namespaces (not in the sense of the `namespace` keyword in C++). http://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions/1675446#1675446 – David Rodríguez - dribeas Apr 14 '10 at 08:25
4

In C there are different namespaces for struct names and type names (such as int) {the type namespace is shared with the variable and function namespace, so be aware of that}. When you define a new struct you automatically add its name to the struct namespace, but when you declare a variable of that type you have to preceed it's name with struct so that the compiler knows to look in the struct namespace to see what exactly it is that you want this variable to be.

Using the typedef keyword you can add a name for the variable to the type namespace so that you do not have to use the struct keyword in your declarations.

The example you gave combined the typedef declaration with the struct definition, but used different names for the struct in the type namespace and the struct namespace. You are able to do this for two reasons. First, prefixing a statement which looks exactly like a variable declaration with typedef defines a typename instead of a variable with the name specified. Secondly, you can declare variables of a struct type by including their names immediatly after the struct declaration and the semicolon. Your example combined these.

There are other legal forms of this in C. For example:

/* This declares a variable foo whose type has no name but is a struct that contains one int named x */
struct {
    int x;
} foo;

/* This adds bar to the type namespace without adding an entry to the struct namespace. */
typedef struct {
    int y;
} bar;

/* This adds the name baz to the struct namespace and declares a variable named b of this type */
struct baz {
    int z;
} b;

/* This adds the name ralf to the type namespace which also refers to this type */
typedef struct baz ralf;

C++ has different namespace structure, which I'm sure you have noticed since it has the namespace keyword. In this instance though C++ is more simple than C. Defining a struct (or class or union or enum) automatically adds the name you used (if any) to the namespace which typedef adds names to. This simplifies things greatly, for the most part, but there are a few gotchas. These mostly have to do with retaining backward compatibility with C. Mostly this compatibility has to do with noticing when someone typedefs struct foo foo; and not treating it as an error of trying to name something with an already used name.

Another issue comes up with this type of fairly common C code:

struct shoe {
    int size;
} shoe;

This is common in C particularly when only one of a struct needs to exist. In C this would be easy because there would be no collision between the names of the struct shoe and the variable shoe. In C++ this still works though to maintain backwards compatibility with C.

nategoose
  • 12,054
  • 27
  • 42
1

None of this applies to C++. In C++ prefer:

struct Foo
{
   . . .
};

The rest only applies to C.

Technically struct Foo {}; is sufficient for most purposes. However it is a bit verbose to use as struct must be repeated each time type Foo is used.

struct Foo {}

void func( struct Foo* foo );

A typedef makes this simpler.

struct Foo { };
typedef struct Foo Foo;
void func( Foo* foo );

This can be further shortened with:

typedef struct Foo { } Foo;
void func( Foo* foo );

When doing a one liner it's also possible to use this syntax:

typedef struct { } Foo;
void func( Foo* foo );

This is creating an anonymous struct and then giving it the name Foo. You see this most often with enums.

typedef enum { } Bar;

There is a reason the intial redundant Foo is usually left there. It is only only way to create a self referencing struct, like a linked list.

typedef struct Node
{
   Node* next;
} Node;

If the initial Node where ommited there would be no way to declare a pointer to the struct. Technically this is valid as well, but now you have to come up with 2 names, instead of just one.

typedef struct node_
{
   node_* next;
} Node;

So why use:

typedef struct Foo { } Foo;

For uniformity. This declaration style covers all you bases, so you never have to think about it when declaring a struct.

deft_code
  • 57,255
  • 29
  • 141
  • 224
0

Student is the name of the new type the typedef has created. StudentRec is the name of the structure it defines.

Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61