在刚开始学习C语言时,遇到复杂声明的时候,总是搞不清楚应该怎样去读声明,因此在学习过程中走过许多弯路。慢慢地,我逐渐掌握了一些读复杂声明的办法。以下纯属个人理解。
首先,要明确一些常识:
1、int a;//代表a是一个整型变量
2、int *a;//代表a是一个指向整形变量的指针
3、int a[5];//代表a是一个有着5个整型元素的数组
4、int a();//代表a是一个返回值为整型的函数
5、int *a();//代表a是一个返回值为指向整形变量的指针的函数
其次,要明确一些声明中常用运算符的优先级问题。这里我打算从下面几个例子中说明:
1.int *a[5]和int (*a)[5]的区别
先分析int *a[5],[]的优先级比 * 优先级要高,所以a先与[]结合,a就变为了一个有着5个元素的数组,即等价于int *(a[5]),而每个数组元素为指向整型变量的指针。
再分析int (*a)[5],()优先级最高,所以a先与 * 结合,a就变成了一个指针,然后,我们假设m=(*a),那么上面就变为int m[5],这里m是一个有着5个整型元素的数组,而(*a)=m中,*表示解析引用符,说明指针a指向的内容是m,也就是说,a是一个指向有着5个整型元素数组的指针。
2.int *a()和int (*a)()的区别
int *a()很直观,a代表返回值为指向整型变量的指针的函数
分析int (*a)(),()优先级最高,所以a先与 * 结合,a就变成了一个指针,然后,我们假设m=(*a),那么上述声明就变为int m(),这里m是返回值为整型变量的函数,而(*a)=m说明a是一个指向m的指针,也就是说,a是一个指向返回值为整型变量的函数的指针(函数指针)。
实战练习(节选于《C程序设计语言(第二版)》):
1、char (*(*x())[ ])()
首先,找到最里面的括号,x()代表x为一个函数,然后(*x())代表x是一个返回值为指针的函数,假设用m代替(*x()),则上述声明变成char (*m[])()。
对于char (*m[])(),m先与[]结合变成数组,再与 * 结合,表示该数组里的元素为指针,则m是一个元素为指针的数组,假设用n代替(*m[]),则上述声明又变成了char n(),此时n表示返回值为char型的函数,而(*m[])=n中,*为解析引用符,上面表达式表示m中的元素为指向n的指针,即m中的元素为指向返回值为char型的函数的指针。
而在(*x())=m中,x()等于函数x返回的指针,*为间接取地址符,所以(*x())=m表示的含义是函数x返回的指针指向的内容为m。
综上,可以知道x是一个返回值为指针的函数,而指针指向的内容为一个数组,而该数组的元素为指向返回值为char型的函数的指针。(有点晕)
2、char (*(*x[3])())[5]
首先,找到最里面的括号,*x[3]表示x是一个有着3个元素的数组,而每个元素是一个指针,假设用m代替(*x[3]),则上述声明变成char (*m())[5]。
再来分析char (*m())[5],(*m())表示m是返回值为指针的函数,再假设用n代替(*m()),则上述声明又变成了char n[5],而这说明n为一个有着5个char型元素的数组。而在(*m())=n中,m()等于函数m返回的指针,*表示解析引用符,所以表达式说明函数m返回的指针指向的内容是n(n为一个有着5个char型元素的数组)。
而在(*x[3])=m中,*表示解析引用符,说明x数组中的每一个指针指向的内容为m(m为返回值为指针的函数)。
综上,可以知道x是一个数组,其中每一个元素为一个指针,该指针指向的内容为一个返回值为指针的函数,而函数返回的指针指向的是一个有着5个char型元素的数组。
(山路十八绕,第一次打这么字,累死我了)