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

Why are there two names for a struct in this C code?

我一直在使用书中的一些示例代码 "Learning Core Audio" 就像这样..

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

为什么 "MySineWavePlayer" 在这段代码中出现了两次?

在这种情况下实际上不需要第一个,如果您这样写

,则第二个用于typedef
struct MySineWavePlayer
{
  AudioUnit outputUnit;
  double startingFrameCount;
};

然后你需要做这样的事情来声明一个 struct

的实例
struct MySineWavePlayer mySineWavePlayer;

然后你可以这样做

typedef struct MySineWavePlayer MySineWavePlayer;

然后声明将变为

MySineWavePlayer mySineWavePlayer;

所以原来的

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

是这些的组合。

你甚至可以为匿名结构typedef

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

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

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

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

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

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

在第一行中,您在结构名称 space 中定义标识符 S(不是 C++ 意义上的)。您可以使用它并通过将参数类型定义为 struct S:

来定义新定义类型的变量或函数参数
void f( struct S argument ); // struct is required here

第二行在全局名称 space 中添加了一个类型别名 S,因此您可以只写:

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

请注意,由于两个标识符名称 spaces 不同,因此在结构和全局 spaces 中定义 S 不是错误,因为它不是重新定义相同的标识符,而是在不同的地方创建不同的标识符。

为了让区别更清楚:

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

您可以定义一个与结构同名的函数,因为标识符保存在不同的 space 中,但是您不能定义一个与 typedef 同名的函数,因为这些标识符会发生冲突。

在 C++ 中,它略有不同,因为定位符号的规则发生了微妙的变化。 C++ 仍然保留了两个不同的标识符 space,但与 C 不同的是,当您只在 class 标识符内定义符号 space 时,您不需要提供 struct/class 关键词:

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

搜索规则有什么变化,而不是标识符定义的地方。编译器将搜索全局标识符 table,在未找到 S 后,它将在 class 标识符中搜索 S

之前提供的代码以相同的方式运行:

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

在第二行定义 S 函数后,编译器无法自动解析结构 S,要创建对象或定义该类型的参数,您必须回退到包括结构关键字:

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

source