5

Theres some sample code I have been working with from the book "Learning Core Audio" like so..

typedef struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;

Why is "MySineWavePlayer" in this code twice?

sbooth
  • 16,646
  • 2
  • 55
  • 81
benstpierre
  • 32,833
  • 51
  • 177
  • 288
  • Also see http://stackoverflow.com/questions/15462475/typedef-struct-usage or http://stackoverflow.com/questions/1110944/c-typedef-and-struct-question – Rob Jan 10 '15 at 00:34

2 Answers2

14

This is a common question which is answered by explaining the difference between using typedef when defining a struct and not using typedef.

The common idiom is using both: typedef struct X { int x; } X;

They are different definitions. To make the discussion clearer I will split the sentence:

struct S { int x; };
typedef struct S S;

In the first line you are defining the identifier S within the struct name space (not in the C++ sense). You can use it and define variables or function arguments of the newly defined type by defining the type of the argument as struct S:

void f( struct S argument ); // struct is required here

The second line adds a type alias S in the global name space and thus allows you to just write:

void f( S argument ); // struct keyword no longer needed

Note that since both identifier name spaces are different, defining S both in the structs and global spaces is not an error, as it is not redefining the same identifier, but rather creating a different identifier in a different place.

To make the difference clearer:

typedef struct S { int x; } T;
void S() {} // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'

You can define a function with the same name of the struct as the identifiers are kept in different spaces, but you cannot define a function with the same name as a typedef as those identifiers collide.

In C++, it is slightly different as the rules to locate a symbol have changed subtly. C++ still keeps the two different identifier spaces, but unlike in C, when you only define the symbol within the class identifier space, you are not required to provide the struct/class keyword:

 // C++
 struct S { int x; }; // S defined as a class
 void f( S a ); // correct: struct is optional

What changes are the search rules, not where the identifiers are defined. The compiler will search the global identifier table and after S has not been found it will search for S within the class identifiers.

The code presented before behaves in the same way:

typedef struct S { int x; } T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'

After the definition of the S function in the second line, the struct S cannot be resolved automatically by the compiler, and to create an object or define an argument of that type you must fall back to including the struct keyword:

// previous code here...
int main() {
    S(); 
    struct S s;
}

source

Community
  • 1
  • 1
David.Jones
  • 1,413
  • 8
  • 16
  • who is asking about `c++`? – Iharob Al Asimi Jan 10 '15 at 00:31
  • @iharob What c++? except for the c++ style comments, this is straight C - oops just saw the second half which explains c++ subtleties. never mind – Arlie Stephens Jan 10 '15 at 02:01
  • @ArlieStephens if this was c++ the whole question would make no point since in c++ you don't need the `typedef`. – Iharob Al Asimi Jan 10 '15 at 03:24
  • 3
    @iharob: The question was not about C++, that's right, but I think the different behaviour in C and C++ is worth explaining. The OP's question has been answered after all and the C++ part ist just extra information. – M Oehm Jan 10 '15 at 08:27
6

the first one is actually not needed in this case, the second one is for the typedef if you write this

struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
};

then you need to do something like this to declare an instance of struct

struct MySineWavePlayer mySineWavePlayer;

you can then do this

typedef struct MySineWavePlayer MySineWavePlayer;

and then the declaration would become

MySineWavePlayer mySineWavePlayer;

so the original one

typedef struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;

is a combination if these.

And you could even do the typedef for an anonymous struct

typedef struct
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;

So short answer is first MySineWavePlayer is the name of the struct while the second is the name of the typedefd type.

CRD
  • 52,522
  • 5
  • 70
  • 86
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Technically the first of the two is needed unless you are declaring an anonymous struct. If you want to manually code `struct S myStruct`, you can no longer do that. – Cloud Jan 10 '15 at 03:20
  • True, but why to do the `typedef` then, if you want to code `struct S myS;` then no need for the `typedef`. – Iharob Al Asimi Jan 10 '15 at 03:23
  • It would be non-sensical yes, but it would change one ability of the coder. The only actual example where it would be necessary is some old pre-C89 example I worked with a couple years back where it didn't like typedef'ed struct definitions like those above. – Cloud Jan 10 '15 at 03:25