没有合适的资源?快使用搜索试试~ 我知道了~
超强的指针学习笔记 C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方...
需积分: 12 9 下载量 152 浏览量
2010-08-04
17:45:32
上传
评论 2
收藏 62KB DOC 举报
温馨提示
试读
16页
C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左 法则其实并不是C标 准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩 识一个声明的,两者可 以说是相反的。右左法则的英文原文是这样说的: 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 标准的声明规定中归纳出来的方法。C 标准的声明规则,是用来解决如何创建声明
的,而右左法则是用来解决如何辩 识一个声明的,两者可 以说是相反的。右左法则的英
文原文是这样说的:
Theright-leftrule:Startreadingthedeclarationfromtheinnermostparenthe
ses,goright,andthengoleft.Whenyouencounterparentheses,thedirection
shouldbereversed.Onceeverythingintheparentheseshasbeenparsed,jum
poutofit.Continuetillthewholedeclarationhasbeenparsed.
这段英文的翻译如下:
右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就
应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直
到整个声明解析完毕。
笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不
是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未
定义的标识符只会有一个。
现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:
int(*func)(int*p);
首先找到那个未定义的标识符,就是 func,它的外面有一对圆括号,而且左边是一个*号,
这说明 func 是一个指针,然后跳出这个圆括号,先看右 边,也 是一个圆括号,这说明
(*func)是一个函数,而 func 是一个指向这类函数的指针,就是一个函数指针,这类函数
具有 int*类型的形参,返回值 类型 是 int。
int(*func)(int*p,int(*f)(int*));
func 被一对括号包含,且左 边有一个 *号,说明 func 是一个指针,跳出括号,右边也有
个括号,那么 func 是一个指向函数的指针,这类函数具有 int*和 int(*) (int*)这样的形
参,返回值为 int 类型。再来看一看 func 的形参 int(*f)(int*),类似前面的解释,f 也是
一个函数指针,指向的函数 具有 int*类型的形参,返回值为 int。
int(*func[5])(int*p);
func右边是一个[]运 算符,说明 func 是一个具有 5 个元素的数组,func 的左边有一个*,
说明 func 的元素是指针,要注意这里的*不是修饰 func 的, 而是修饰 func[5]的,原因
是[]运算符优先级比*高,func 先跟[]结合,因此*修饰的是 func[5]。跳出这个括号,看
右边,也是一对圆括 号,说明 func 数组的元素是函数类型的指针,它所指向的函数具有
int*类型的形参,返回值类型为 int。
int(*(*func)[5])(int*p);
func 被一个圆括号包含,左边又有一个*,那么 func 是一个指针,跳出括号,右边是一
个[]运算符号,说明 func 是一个指向数组的指针,现在往左看,左边有 一个*号,说明这
个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数
的指针。总结一下,就是:func 是一个指向数组的 指 针,这个数组的元素是函数指针,
这些指针指向具有 int*形参,返回值为 int 类型的函数。
int(*(*func)(int*p))[5];
func 是一个函数指针,这类函数具有 int*类型的形参,返回值是指向数组的指针,所指
向的数组的元素是具有 5 个 int 元素的数组。
要注意有些复杂指针声明是非法的,例如:
intfunc(void)[5];
func 是一个返回值为具有 5 个 int 元素的数组的函数。但 C 语言的函数返回值不能为数组,
这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数
组,但 C 语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值
不能为数组。
intfunc[5](void);
func 是一个具有 5 个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组
的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达
到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。
作为练习,下面列几个复杂指针声明给读者自己来解析,答案放在第十章里。
int(*(*func)[5][6])[7][8];
int(*(*(*func)(int*))[5])(int*);
int(*(*func[7][8][9])(int*))[5];
实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程
序可读性是一大损害。应该用 typedef 来对声明逐层分解,增强可读性,例如对于声明:
int(*(*func)(int*p))[5];
可以这样分解:
typedefint(*PARA)[5];
typedefPARA(*func)(int*);
这样就容易看得多了。
==============================================
=================
转载述: 这是一篇比较老的关于指针的文章,作者站在初学者的角度对指针作了深入的
剖析。如果你在学习指针的时候有什么问题,看一看这篇文章定有收获。
一。指针的概念
1。指针的类型
2。指针所指向的类型
3。指针的值
二。指针的算术运算
三。运算符&和*
四。指针表达式
五。数组和指针的关系
一。指针的概念
指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。
要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指
针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。
先声明几个指针放着做例子:
例一:
(1)int*ptr;
(2)char*ptr;
(3)int**ptr;
(4)int(*ptr)[3];
(5)int*(*ptr)[4];
如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<如何理解 c 和 c++的复杂
类型声明>>。
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 越来越熟
悉时,你会发现,把与指针搅和在一起的“类型”这个概念分成“指针的类型 ”和“指针所指向
的类型”两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就
把指针的这两个概念搅在一起了,所以看起书来前后 矛 盾,越看越糊涂。
3。 指针的值
指针的值,或者叫指针所指向的内存区或地址。 指针的值是指针本身存储的数值,这
个值将被编译器当作一个地址,而不是一个一般的数值。在 32 位程序里,所有类型的指
针的值都是一个 32 位整数,因为 32 位程序里内存地址全都是 32 位长。
指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为 sizeof(指
针所指向的类型)的一片内存区。以后,我们说一个指针的值是 XX,就 相当于说该指针
指向了以 XX 为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于
说该指针的值是这块内存区域的首地址。
指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所
指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者
说是无意义的。
以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的类型是什
么?该指针指向了哪里?
4。 指针本身所占据的内存区。
指针本身占了多大的内存?你只要用函数 sizeof(指针的类型)测一下就知道了。在 32
位平台里,指针本身占据了 4 个字节的长度。
指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。
二。指针的算术运算
指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意
义是不一样的。例如:
例二:
1。 chara[20];
2。 int*ptr=a;
剩余15页未读,继续阅读
资源评论
feixiangmenghuan
- 粉丝: 56
- 资源: 38
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功