指针 - 函数定义中结构后的“*”是什么意思?

Pointers - What does a '*' after a struct mean in the function definition?

我正在学习 C 中的指针。我遇到了一个我不理解 return 类型的函数。函数定义为: extern PHONE* findPhone()

PHONE 是一个结构。函数 return 是一个 PHONE 指针。如果它想这样做,函数定义中的 return 类型不应该是 '*PHONE'

此位置的星号是 声明符 语法的一部分。它表示一个指针。

在 C 语言中,声明 是一个 declaration-specifiers 列表,后跟一个 声明符列表 带有可选的初始化。

declaration-specifiers 指定类型,如 intdoublelong longstruct foo 或类型定义名称。 (它们还包括其他类型的说明符,如 externinline,这些说明符在此答案中无关紧要。)无论类型如何 <i>T</i> 这是,声明符然后指定具有 <i>T</i>.

类型的事物

声明符有几种形式:

  • 一个普通的名字,<i>D</i>,表示<i>D</i> 的类型为 <i>T</i>.
  • 圆括号中的声明符,(<i>D</i>),表示表达式(<i>D</i>) 的类型为 <i>T</i>,表示 <i>D</i> 也有类型 <i>T</i>,因此这与声明符中的普通名称具有相同的含义。但是,它将声明符分组以进行进一步解析。
  • 带括号的声明符,<i>D</i>[<em>expression</em>],表示表达式<i>D</i>[i] 将具有类型 <i>T</i>,这意味着<i>D</i> 必须是类型数组。
  • 带有星号的声明符,*<i>D</i>,表示表达式 *<i>D</i> 将具有类型 <i>T</i>,因此 <i>D</i> 必须是指向 <i>T</i>.
  • 的指针
  • 带括号的声明符,<i>D</i>(),表示表达式<i>D</i>() 将具有类型 <i>T</i>,这意味着 <i>D</i> 必须是 returns <i>T</i>.
  • 的函数

这些表格可以组合。声明符 (*<i>D</i>)[] 表示 (*<i>D</i>)[] 具有类型 <i>T</i>,因此 (*<i>D</i>)<i>T</i>的数组,所以*<i>D</i>也是<i>T</i>的数组,所以<i>D</i> 是指向 <i>T</i>.

数组的指针

从本质上讲,声明符是一个名称将如何在表达式中使用的图片,名称的实际类型是通过从该表达式的类型向后计算得出的。

所以extern PHONE* findPhone()在语法上是extern PHONE* findPhone()。它说 * findPhone() 的类型是 PHONE。所以 findPhone() 是一个指向 PHONE 的指针。所以 findPhone 是一个返回指向类型 PHONE.

的指针的函数

(上面没有讨论声明符的其他部分,例如函数的参数列表和声明数组时括号内容的一些选项。)

extern PHONE* findPhone()

被解析为

extern PHONE (*findPhone())

C 中的声明分为两个主要部分 - 随后是一系列 声明说明符 (类型说明符、存储 class 说明符、类型限定符等)通过 comma-separated 个 声明符列表 .

Array-ness、function-ness 和 pointer-ness 被指定为声明符的一部分。在上面的声明中,extern PHONE 是声明说明符,*findPhone() 是声明符;它表示 findPhone() 函数 returns 指向 PHONE.

的指针

想法是声明符的结构与同一类型代码中表达式的结构相匹配。在这种情况下,如果您想访问函数 returns 的 PHONE 对象,您将调用该函数并取消引用结果:

a_phone = *findPhone();

表达式*findPhone()的类型是PHONE,因此函数的声明是

PHONE *findPhone();

除了分隔相同类型的标记(例如 externPHONE,它们都是标识符)之外,空格并不重要。因为 * 字符永远不能成为标识符的一部分,所以写

也没关系
extern PHONE* findPhone();

extern PHONE *findPhone();

extern PHONE    *     findPhone()     ;

甚至

extern PHONE*findPhone();

它们都将以相同的方式解释。