C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:

The right-left rule: Start reading the declaration from theinnermost parentheses, go right, and

then go left. When you encounter parentheses, the direction shouldbe reversed. Once everything

in the parentheses has been parsed, jump out of it. Continue tillthe whole declaration has been

parsed.

这段英文的翻译如下:

右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。

一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。

而我要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以

是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。

现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:

int (*func)(int *p);

sizeof( func ) = 4, 它是一个函数指针,在32位系统中一个指针占4字节。

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指

针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类

函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值 类型是 int。

int (*func)( int *p, int (*f)(int*) );

sizeof( func ) = 4

func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一

个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形

参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。

int (*func[5])(int *p);

sizeof( func ) = 20  它是一个数组,有五个元素,每个元素都是指针,所以总共占了 5x4=20 B的空间。

这里有点复杂,用typedef分解看的比较清楚:

typedef int f(int *p);  这是一个函数;

typedef f   *pf;          这是函数 指针;

typedef pf  apf[5];    函数指针 类型的 数组;

也就是 它是一个 含有 五个 函数指针 元素 的数组

func 右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针

,要注意这里的*不是修饰func的, 而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因

此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它

所指向的函数具有int*类型的形参,返回值类型为int。

int ( * (*func)[5] )(int *p);

sizeof( func ) = 4 它是指针,所以只占四个字节

typedef int f(int *p);  这是一个函数;

typedef f   *pf;          这是函数 指针;

typedef pf  apf[5];    这是一个函数指针 数组

typedef apf*papf;   它是指针

func 被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明

func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边

又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指 针,这个

数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。

int ( *(*func)(int *p) )[5];

sizeof( func ) =4     它是指针

typedef int   a[5];     首先它是一个数组,

typedefa     *pa;       它是一个指向数组的指针,指向数组的指针的表示: int  (*a)[5]

typedef pa fpa( int *p);  函数的返回值为pa,而pa是一个数组指针

typedef fpa*pfpa;   它只是个指针

func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5

个int元素的数组。

注意:

int *( *p )[5] 和 int (* (*p) )[5]在用typedef分解时先后顺序是不同的:

int *( *p )[5]

typedef   int*p;    首先它是一个指针

typedef   pap[5];  一个数组的5个元素类型也是指针  即指针修饰的是数组的元素

typedef  ap   *pap; 最后它是一个指向数组的指针

int (* (*p) )[5] typedef  int a[5];   首先它是一个数组

typedef  a    *pa;   它是一个指向数组的指针

typedef   pa *ppa;它是一个指向数组指针的指针

要注意有些复杂指针声明是非法的,例如:

int func(void) [5];

func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数

返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作

为左值来接收另一个数组,因此函数返回值不能为数组。

int func[5](void);

func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样

外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数

所占用的空间通常是不相同的。

附:

1、 指针的类型

从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针

本身所具有的类型。让我们看看例一中各个指针的类型:(1)int *ptr; //指针的类型是int *

(2)char *ptr; //指针的类型是char *

(3)int **ptr; //指针的类型是 int **

(4)int (*ptr)[3]; //指针的类型是 int(*)[3]

(5)int *(*ptr)[4]; //指针的类型是 int *(*)[4]怎么样?找出指针的类型的方法是不是很简单?

2、指针所指向的类型

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当

做什么来看待。    从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符 *去掉,剩下的就是指针所指

向的类型。例如:(1)int *ptr; //指针所指向的类型是int

(2)char *ptr; //指针所指向的的类型是char

(3)int **ptr; //指针所指向的的类型是 int *

(4)int (*ptr)[3]; //指针所指向的的类型是 int()[3]

(5)int *(*ptr)[4]; //指针所指向的的类型是 int *()[4]

在指针的算术运算中,指针所指向的类型有很大的作用。    指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把

与指针搅和在一起的“类型”这个概念分成“指针的类型 ”和“指针所指向的类型”两个概念,是精通指针的

关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后

矛盾,越看越糊涂。

c语言指针在左还是右,C语言学习之指针的右左法则相关推荐

  1. 【C语言重点难点精讲】C语言指针

    文章目录 一:指针入门 二:数组入门 (1)数组的内存空间布局 (2)区分&arr[0]和&arr 三:指针和数组的关系 (1)以指针的形式访问和以数组形式访问 (2)为什么C语言要这 ...

  2. 按照c语言规首字母只能是,C语言--指针 - osc_nbqoh20k的个人空间 - OSCHINA - 中文开源技术交流社区...

    [TOC] #知识内容总结 ##为什么要学习指针? 我们已经学习了如何用数组存放多个相同类型的数据并进行运算,但数组的长度在定义时必须给定以后不能再改变.如果事先无法确定需要处理数据数量,应该如何处理 ...

  3. c语言未初始化的指针下标访问是0,C语言的二数组的指针访问.doc

    C语言的二数组的指针访问 二维数组的指针访问 --王炳华 指向二维数组的指针及用指针访问二维数组,是学习指针的最大难点.如果真正弄懂了这个问题,就可以说你学会了使用指针. 二维数组的指针 指针就是地址 ...

  4. 《你必须知道的的495个C语言问题》阅读笔记-(第4章)指针篇

    指针是C的精华,也是初学者的梦魇 4.1 FAQ:指针的好处有哪些? Answer:(1)可以动态分配数组: (2)可以对多个相似变量一般访问: (3)按照引用传递函数参数: (4)适合各种动态分配的 ...

  5. c语言指针b 和b j,c语言精华 ------ 指针和数组

    一.指针. 它的本质是地址的类型.在许多语言中根本就没有这个概念.但是它却正是C灵活,高效,在面向过程的时代所向披靡的原因所在.因为C的内存模型基本上对应了现在von Neumann(冯·诺伊曼)计算 ...

  6. c语言常量l12和意义,课件c语言l12_指针和数组

    <课件c语言l12_指针和数组>由会员分享,可在线阅读,更多相关<课件c语言l12_指针和数组(42页珍藏版)>请在人人文库网上搜索. 1.计算机程序设计基础第12讲指针和数组 ...

  7. char类型怎么输入 c语言_还没搞懂C语言指针?这里有最详细的纯干货讲解(附代码)...

    21ic综合自网络信息 指针对于C来说太重要.然而,想要全面理解指针,除了要对C语言有熟练的掌握外,还要有计算机硬件以及操作系统等方方面面的基本知识.所以本文尽可能的通过一篇文章完全讲解指针. 为什么 ...

  8. c语言中指针往内存写值,C语言编程常见问题解答之指针和内存分配

    指针为C语言编程提供了强大的支持--如果你能正确而灵活地利用指针,你就可以直接切入问题的核心,或者将程序分割成一个个片断.一个很好地利用了指针的程序会非常高效.简洁和精致. 利用指针你可以将数据写入内 ...

  9. java char指针数组_简单总结C语言中各种类型的指针的概念

    C语言中有很多关于指针的使用,指针也是C语言的灵魂所在,而且C语言中也有很多有关指针的概念,这里学习并总结了一些知道的概念. 常量指针:首先它是一个指针,常量只是用来修饰指针的定语.其定义如下: ch ...

最新文章

  1. #define 用法
  2. python基本使用-python基本用法笔记合集
  3. Jquery Mobile --小知识
  4. hdu 5606(并查集)
  5. 【工作感悟】java编程规范pdf下载
  6. Zookeeper集群安装(开启kerberos)
  7. 三点拓宽自己的工作思路
  8. SUSE Labs Con 2018有感
  9. 蓝桥杯2016年七届C/C++省赛C组第三题-平方怪圈
  10. net core体系-web应用程序-4asp.net core2.0 项目实战(CMS)-第二章 入门篇-快速入门ASP.NET Core看这篇就够了...
  11. 后台管理系统下载excel文件
  12. 常用遥感数据下载地址
  13. papi酱微博数据可视化(截至2020年12月9日)
  14. 邮件这样写,PK 掉 99% 的同事
  15. 基于云服务创建弹性托管集群服务
  16. LCD液晶屏连接方式有哪些呢及各自优缺点是什么?
  17. 2019年最新的一波手机APP分享,每一个都是大家的菜哦!
  18. Could not find parameter map
  19. 一文学会目前最火热的大数据技术
  20. Android 批量打包 基于Walle的多渠道快速打包自动脚本

热门文章

  1. EventLoopGroup 与Reactor 关联
  2. ArrayBlockingQueue原理分析-itrs.elementDequeued()
  3. 区域数据导入功能(POI使用方式)
  4. 常用的函数式接口_Predicate接口
  5. Eureka集群部署
  6. 什么是Eureka注册中心
  7. Fegion-3覆写Fegion的默认配置及Fegion的日志
  8. Redis分布式锁原理解析
  9. (java ee,Eclipse J2EE最新版官方下载(Eclipse for Java EE Developers)
  10. MySQL执行原理,逻辑分层、更改数据库处理引擎