【C深入】指针阅读技巧解析

现在很多IT公司都会有一些关于复杂声明的面试题,那么我们应该怎么解决这个问题呢?可以利用 右左法则 。这是一个简单的法则,但可以让我们准确理解所有的声明。

   The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

这个法则运用如下:

  右左法则:首先从最里面的圆括号(应该是未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。


  右左法则不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的。


下面是一道面试题,我们可以通过分析这道题来学会使用右左法则。

用变量a给出下面的定义:

1、一个整数(An integer

2、一个指向整型数的指针(A pointer to an integer)

3、一个指向指针的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer

4、一个有10个整型数的数组(An array of 10 integers

5、一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers

6、一个指向有10个整型数组的指针(A pointer to an array of 10 integers

7、一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer
8、一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型(An array of ten pointers to functions that take an integer argument and return an integer


答案如下:

  1. ( 1) int a; //整型变量
  2. ( 2) int *a; //整型指针变量
  3. ( 3) int **a; //整型指针的指针变量
  4. ( 4) int a[ 10]; //整形数组
  5. ( 5) int *a[ 10]; //整型指针数组
  6. ( 6) int (*a)[ 10]; //整型数组指针变量
  7. ( 7) int (*a)( int); //函数指针变量
  8. ( 8) int (*a[ 10])( int); //函数指针数组


  我们来利用右左法则一个一个分析。


(1)int a;

  首先我们先找到变量名a,然后我们看向变量名的右边,这时我们看到一个“;”,说明a是一个变量,那么这个变量保存的是什么值呢?接下来向左看,这时我们看到“int”,这时我们便确定在变量a里存放的是整型值,即整型变量。


  小结:如果a是一个变量,那么接下来要确定这个变量里存放的是什么值。


(2)int *a;

  首先我们找到变量名a,然后向右看,看到了“;”,说明a是一个变量;再向左看,看到了“*”,说明这个变量里存放的都是地址,即指针变量,那么该指针变量所指向空间里存放的值是什么类型的呢?而此时右边已经没有了,所以我们继续向左看,看到“int”,说明指针变量所指向空间里保存的值是整型的,即整型指针变量。


  小结:如果确定变量a里保存的是地址,那么a就是一个指针变量,然后便要确定指针变量所指向空间里保存的值是什么类型。


(3)int **a;

  首先我们可以很快判断出a是一个指针变量,那么接下来便要确定这个指针变量所指向的空间里保存的值是什么类型的,而此时右边已经没有了,那么我们向左看,看到一个“*”,说明这个指针变量所指向空间里保存的还是地址类型的,即指针的指针;再向左看,看到“int”,说明地址所指向空间里的值是整型。即这个地址是指针变量的地址,并且里面保存的类型是整型,即整型指针的指针变量。


  小结:如果确定a是一个指针变量,又确定了这个指针变量里保存的还是指针,那么这便是指向指针的指针,继而确定指针指向空间里保存的是什么类型的地址。


(4)int a[10];

  首先我们往变量名a的右边看,看到一个“【”,说明a是数组,那么接下来就要确认这个数组里的每一个元素里存放的是什么值;向左看,看到“int”,即整型数组。


  小结:如果变量名a向右看是“【”,那么a便是数组。接下来就要确定这个数组的每一个元素存放的是什么类型的值,存放的是什么类型便是什么类型的数组。


(5)int *a[10];

  首先我们确定a是一个数组,向右看,看到“*”,证明这个数组里的每一个元素存放的都是地址,即指针数组,那么接下来便要确认指针指向的空间里的值的类型。再向右看,看到“;”,这时返回,再向左看,看到“int”,证明地址是整型的。即整型指针数组。


(6)int (*a)[10];

  首先我们找到变量a,向右看,看到“)”,返回向左看,看到“*”,便确定a是一个指针变量,再向右看,看到“【”,说明指针变量里保存的地址是数组的地址,即数组指针变量,再向右看,看到“int”,说明这个数组指针变量里的每一个元素都是整型的,即整型数组指针变量。


  小结:指针变量指向什么类型的,就是什么类型的指针变量。


(7)int (*a)(int);

  首先我们确定a是一个指针变量,向右看,看到“(”,说明这个指针变量里保存的是函数,即函数指针变量;而这个函数的形参是整型的,返回值也是整型。


  小结:如果确定a是一个指针变量,并且向右看看到“(”,即指针变量指向函数,即函数指针变量。


(8)int (*a[10])(int);

  首先我们确定a是一个指针数组,而这个指针指向函数,即为函数指针数组,并且函数的形参为整型,返回值也是整型。



下面结合一些比较复杂的例子来演示一下“右左法则”的使用。
(这里参考并使用了“梁庚 陈明 马小陆 编著的《高质量嵌入式Linux C编程》”的部分内容)。 

int * (* (*fp1) (int) ) [10];

阅读步骤: 
1. 从变量名开始 -------------------------------------------- fp1  
2. 往右看,什么也没有,碰到了),因此往左看,碰到一个* ------ 一个指针  
3. 跳出括号,碰到了(int) ----------------------------------- 一个带一个int参数的函数  
4. 向左看,发现一个* --------------------------------------- (函数)返回一个指针  
5. 跳出括号,向右看,碰到[10] ------------------------------ 一个10元素的数组  
6. 向左看,发现一个* --------------------------------------- 指针  
7. 向左看,发现int ----------------------------------------- int类型 

总结:fp1被声明成为一个函数的指针,该函数返回指向指针数组的指针. 


再来看一个例子: 

int *( *( *arr[5])())(); 

阅读步骤: 
1. 从变量名开始 -------------------------------------------- arr  
2. 往右看,发现是一个数组 ---------------------------------- 一个5元素的数组  
3. 向左看,发现一个* --------------------------------------- 指针  
4. 跳出括号,向右看,发现() -------------------------------- 不带参数的函数  
5. 向左看,碰到* ------------------------------------------- (函数)返回一个指针  
6. 跳出括号,向右发现() ------------------------------------ 不带参数的函数  
7. 向左,发现* --------------------------------------------- (函数)返回一个指针  
8. 继续向左,发现int --------------------------------------- int类型 

总结:arr被声明成为一个函数的数组指针,该函数返回指向函数指针的指针。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值