为什么这个C代码中的结构有两个名称?

ben*_*rre 3 c objective-c

我一直在使用"学习核心音频"这本书中的一些示例代码.

typedef struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

为什么此代码中的"MySineWavePlayer"两次?

Dav*_*nes 11

这是一个常见的问题,通过解释在定义结构时使用typedef而不使用typedef之间的区别来回答.

常见的习语是同时使用: typedef struct X { int x; } X;

它们是不同的定义.为了使讨论更清楚,我将分开句子:

struct S { int x; };
typedef struct S S;
Run Code Online (Sandbox Code Playgroud)

在第一行中,您将S在结构名称空间中定义标识符(而不是在C++意义上).您可以使用它并通过将参数的类型定义为struct S:定义新定义类型的变量或函数参数:

void f( struct S argument ); // struct is required here
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

source

  • @iharob:问题不是关于C++,这是对的,但我认为C和C++中的不同行为值得解释.毕竟OP的问题已得到解答,而C++部分只是额外的信息. (3认同)

Iha*_*imi 5

在这种情况下实际上不需要第一个,第二个用于typedef如果你写这个

struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
};
Run Code Online (Sandbox Code Playgroud)

那么你需要做这样的事情来声明一个 struct 的实例

struct MySineWavePlayer mySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做

typedef struct MySineWavePlayer MySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

然后声明将成为

MySineWavePlayer mySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

所以原来的

typedef struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

是这些的组合。

你甚至可以typedef为匿名结构做

typedef struct
{
  AudioUnit outputUnit;
  double startingFrameCount;
} MySineWavePlayer;
Run Code Online (Sandbox Code Playgroud)

所以简短的回答是第一个MySineWavePlayer是d 类型的名称,struct而第二个是typedefd 类型的名称。