美文网首页
C 解析复杂声明

C 解析复杂声明

作者: Tubetrue01 | 来源:发表于2020-12-17 15:59 被阅读0次

引言

这里会讲解一些在 C 中常常遇到的比较复杂的声明,这些声明可能会劝退你学习 C 的热情,但是相信我,读完这一篇之后,你会发现,再复杂的声明也不过如此嘛。

规则

  • A. 声明从它的名字开始读取,然后按照优先级顺序依次读取。
  • B. 优先级从高到低依次是
         B1. 声明中被括号括起来的那部分。
         B2. 后缀操作符:括号 () 表示这是一个函数;方括号 [] 表示这是一个数组。
         B3. 前缀操作符:星号 * 表示指针。
  • C. 如果 const 或 volatile 关键字的后面紧跟类型说明符(如 int,long 等),那么它作用于类型说明符。在其他情况下,const 和 volatile 关键字作用于它左边紧邻的指针星号。
  • D. restrict 关键字用来修饰指针,一般都是出现在 * 的后边。

简单类型说明

有了以上规则,我们可以一步一步开始了。

  • int p
    这是一个普通的整型变量。
  • int *p
    首先从 p 开始,先与 * 结合,说明 p 是一个指针,然后再与 int 结合,说明指针所指向的内容的类型为 int 。
    总结: p 是一个整型数据的指针。
  • int p[3]
    首先从 p 开始,先与 [] 结合,说明 p 是一个数组,然后与 int 结合,说明数组里的元素是整型的。
    总结: p 是一个由整型数据组成的数组。
  • int *p[3]
    首先从 p 开始,先与 [] 结合,因为其优先级比 * 高,所以 p 是一个数组,然后再与 * 结合,说明数组里的元素是指针类型,然后再与 int 结合,说明指针所指向的内容的类型是整型的。
    总结:p 是一个由整型数据的指针所组成的数组。
  • int (*p)[3]
    首先从 p 开始,先与 * 结合,说明 p 是一个指针然后再与 [] 结合 ,说明指针所指向的内容是一个数组,然后再与 int 结合,说明数组里的元素是整型的。
    总结:所以 p 是一个指向由整型数据组成的数组的指针。
  • int **p
    首先从 p 开始,先与 * 结合,说是 p 是一个指针,然后再与 * 结合,指针所指向的元素是指针,然后再与 int 结合,说明该指针所指向的元素是整型数据。由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针。
    总结:二级指针多出现在为一级指针分配内存的场景下。
  • int p(int)
    从 p 开始,先与 () 结合,说明 p 是一个函数,然后进入 () 里分析,说明该函数有一个整型变量的参数,然后再与外面的 int 结合,说明函数的返回值是一个整型数据。
    总结:p 是一个具有一个 int 类型的参数,返回值为整型的函数。
  • int (*p)(int)
    从 p 开始,先与指针结合,说明P 是一个指针,然后与 () 结合,说明指针指向的是一个函数,然后再与 () 里的 int 结合,说明函数有一个 int 型的参数,再与最外层的 int 结合,说明函数的返回类型是整型。
    总结: p 是一个指向 “具有一个整型参数且返回类型为整型的函数” 的指针。

复杂类型说明

有了以上基础,我们可以挑战一下稍微复杂一点的声明了。

  • int *(*p(int))[3]
    从 p 开始,先与 () 结合,说明 p 是一个函数,然后进入 () 里面,与 int 结合,说明函数有一个整型变量参数,然后再与外面的 * 结合,说明函数返回的是一个指针,然后到最外面一层,先与 [] 结合,说明返回的指针指向的是一个数组,然后再与 * 结合,说明数组里的元素是指针,然后再与 int 结合,说明指针指向的内容是整型数据。
    总结:所以 p 是一个 “具有一个整型参数且返回一个指向由整型指针变量组成的数组” 的指针变量的函数。
  • int *(* p[3])(int)
    从 p 开始,先与 [] 结合,说明 p 是一个数组,在与 * 集合,说明数组的元素是指针,在与 () 集合,说明指针指向的是函数,进入 () 里面,与 int 集合,说明函数有一个整型参数,在与最外边的 * 结合,说明函数返回一个指针,在与 int 结合,说明返回的指针指向一个整型。
    总结:p 是一个 “具有一个 int 类型参数且返回指向 int 类型指针的函数指针组成” 的数组。
  • void (*signal(int, void(*func)(int)))(int)

我们最后以这个著名的函数收尾,这应该算是最复杂的声明了吧,如果还有更复杂的,欢迎大家留言。长话短说,让我们开始吧!

从 signal 开始,先跟 () 结合,说明 signal 是一个函数,进入到 () 里面,该函数有两个参数,一个是 int 类型的,一个是具有 int 类型的参数且无返回值的函数指针(分析:从 func 开始,先与 * 结合,说明 func 是一个指针,与 () 结合,说明这个指针指向一个函数,进入 () 里面,与 int 结合,说明指向的函数有一个 int 类型的参数,最后与 void 结合,说明该函数没有返回值),在与 * 结合,说明函数返回一个指针,在与最右边的 () 集合,说明指针指向一个函数,进入 () 里面,与 int 结合,说明该函数有一个 int 类型的参数,最后与 void 集合,说明该函数没有返回值。

虽然比较复杂,但是我们可以利用 typedef 关键字简化它来对本章进行收尾。

/*
 * 表示 func 是一个函数指针,指向一个参数为 int,返回值为 void 的函数。
 */
typedef void (*func)(int);

/*
 * 表示 signal 是一个函数,它接受两个参数,一个是 int,一个是 func,返回值为 func。
 */
func signal(int, func);

参考

相关文章

  • C 解析复杂声明

    引言 这里会讲解一些在 C 中常常遇到的比较复杂的声明,这些声明可能会劝退你学习 C 的热情,但是相信我,读完这一...

  • 复杂声明 | C语言

    今天看了《C专家编程》里的'分析C语言的声明'一章,终于懂了C语言的复杂声明是怎么解析的。虽然在平时写代码的时候用...

  • C++ 复杂声明

    1、方法也是有类型的,方法的类型由返回类型和形参表决定。比如int F (int)的类型就是去掉方法名,int (...

  • 如何解读复杂的C声明

    C语言中的声明可以非常复杂,例如 有一个著名的right-left法则,可以用来解释复杂的C声明,地址在这里。

  • C++雾中风景番外篇:理解C++的复杂声明与声明解析

    在学习C系列语言的过程之中,理解C/C++的复杂声明一直是初学者很困扰的问题。笔者初学之时也深受困扰,对很多规则死...

  • C语言指针的复杂声明

    前记:最近因为离职有很多很多事情,有些郁闷,导致一直没有更新和学习。 这篇看了好多文章,所以搁浅了很久很久。现在终...

  • c的复杂声明和typedef

    这几个东西,总是个总结了又忘,又搞混淆了,还是写下来好回顾 C语言中声明的优先级规则 C专家编程中提到C语言中声明...

  • C 语言复杂类型声明读写

    读 C 语言的声明应该从右向左读,依次地,各符号指涉其左边的符号。例如: 其中包含 const、int、*、i 这...

  • C语言类型系统与复杂声明

    Ref: Linuc C编程一站式学习 C语言类型系统 不完全类型 分析复杂声明

  • 深入理解C中复杂声明

    最近看了几天的 K&R 的< C程序设计语言 >第二版,当读到的第5.12章的复杂函数声明时,我感觉脑袋不够用了。...

网友评论

      本文标题:C 解析复杂声明

      本文链接:https://www.haomeiwen.com/subject/djiwgktx.html