C语言学习笔记:为什么&相当于升级而*相当于降级?
最近一直在学习北京大学李戈老师在Coursera上的MOOC课程《计算概论A》。在课程的后半部分讲到了C语言的指针运算符
1. 数组名相当于指向数组第一个元素的指针;
2.
3.
利用这三条结论,我们可以非常方便且准确地分析指针运算符在数组中应用时的含义,因此这三条结论十分重要。这三条结论不仅值得花时间记下来,也值得花时间真正搞清楚为什么是这样的,这样才不至于死记硬背。在这里,我根据李戈老师的讲解,用中文将此处知识整理一下,便于学习和复习。
由于多维数组实质上就是嵌套(nested)数组,所谓的“多维”不过是基于这样一个事实:数组也可以作为数组之中的元素。
什么是“表达式
上述结论中涉及到了这样一个概念:“表达式
以整型二维数组
其中前三者(都是指针)存储的值都是该二维数组
通俗地说,指针化的程度越高,表示的范围越大,级别越高。
为什么
首先,当
而当
为什么
&
和*
在数组中的应用。课程中李戈老师通过分析讲解和引用C语言规范文档清晰地讲清楚了这两个运算符的含义,并给出了三条非常重要的结论:1. 数组名相当于指向数组第一个元素的指针;
2.
&E
相当于把E
的管辖范围上升了一个级别;3.
*E
相当于把E
的管辖范围下降了一个级别。利用这三条结论,我们可以非常方便且准确地分析指针运算符在数组中应用时的含义,因此这三条结论十分重要。这三条结论不仅值得花时间记下来,也值得花时间真正搞清楚为什么是这样的,这样才不至于死记硬背。在这里,我根据李戈老师的讲解,用中文将此处知识整理一下,便于学习和复习。
两条事实
由于多维数组实质上就是嵌套(nested)数组,所谓的“多维”不过是基于这样一个事实:数组也可以作为数组之中的元素。
&
运算符只能用在实体(就是变量)前面,*
运算符只能用在指针前面。
什么是“表达式E
的管辖范围(级别)”?
上述结论中涉及到了这样一个概念:“表达式
E
的管辖范围”,也就是“表达式E
的级别”。那么,什么是所谓的“管辖范围”和“级别”呢?以整型二维数组
a[i][j]
为例。以下表达式的“管辖范围”(“级别”)依次降低:&a
指针,指向整个二维数组a
a
指针,指向二维数组a
的第一个元素(一维数组a[0]
)*a
指针,指向二维数组a
的第一个元素(一维数组a[0]
)中的第一个元素(int
变量 a[0][0]
)*a[0]
int变量,就是a[0][0]
其中前三者(都是指针)存储的值都是该二维数组
a
的第一行的首个元素的起始地址,但区别在于所指的“范围”不同。当对它们进行+1运算的时候,跨过的范围是不同的。通俗地说,指针化的程度越高,表示的范围越大,级别越高。
为什么&
表示升级?
首先,当
&
用在多维数组中最基本的元素(而不是数组名,如本例中的a[0][0]
)前面的时候,情况是最简单的:整个表达式表示指向这个元素的指针。而当
&
用在一个数组名前面的时候,由于&
运算符只能用在实体(变量)前面,而根据结论1,一个数组的名字(如本例中二维数组的名字a
和一维数组的名字a[0]
)实质上就是指向该数组第一个元素的指针,因此在&
后接一个数组名(如本例中的&a
和&a[0]
)实质上是在&
后接了一个指针。这个时候怎么处理呢?C语言的规范文档中规定:此时整个表达式是一个指针,并且表示指向整个该数组的指针(在本例中,&a
就是指向整个二维数组a
的指针,&a[0]
就是指向整个一维数组a[0]
的指针)。这样,数组名在前面加上&
运算符后,就由原先“指向该数组的第一个元素的指针”升级为“指向该数组整体的指针”,这样就完成了对&
运算符后接的表达式的“升级”。这就是结论2的含义。
为什么*
表示降级?
*
运算符的情况比较简单一些,因为*
只能用在指针前面,而根据结论1,数组名是指针化的。通俗地说,通过结论1,实体(变量)能变成指针,而指针不能变成实体(变量),因此*
运算符不存在像上述&
运算符那样的人为规定。所以*
运算符就表示指针的实体化。而对于数组而言,指针实体化后所变成的那个实体(变量)如果仍然是数组名(如在本例中,*a
变成a[0]
),则根据结论1,*
运算符将a
(表示指向a[0]
的指针)本身又降了一级,整个表达式表示a[0]
(表示指向a[0][0]
的指针),从而完成了对*
运算符后接的表达式的“降级”。这就是结论3的含义。
评论
发表评论