C语言没有行指针、列指针、指针数组、数组指针、多级指针。。。等等这些概念。
这一系列视频播放了以后,有一些朋友问行指针、列指针、指针数组、数组指针、多级指针这样的概念,在这里,我把一些基本概念捋一下,供大家参考:
1、首先,C语言的标准中,没有行指针、列指针、指针数组、数组指针、多级指针。。。等等这些概念,在C语言标准中没有这样的术语定义。举个例子,假设我们给定一个int a[2][3][4][5][6],那么a[0][0]该怎么看待呢?第二行指针?还是第一列指针?
2、在C语言中,有一个核心的基本概念,就是Type,Type分为对象类型(Object Type)和函数类型(Function Type),任何指针类型都和int,float这些完全一样,也是一种对象类型(只不过指针是一种Derived Type),所以指针的本质上和任何类型都一样,学习指针的最重要一点,就是不要把指针类型特别来看待,指针这种类型和其他基本类型的性质是完全一样的。关于Type的内容,可以参看C语言中Type的概念和含义。
3、在C语言中,数组也是一个Type(数组也是一种Derived Type),比如,对于int a[2]这样一个声明语句,其核心的要点是要理解int[2]是一种合法的Object Type,这个语句的意思是声明了一个对象a,其类型是int[2]。有不少朋友困惑int[2]是一个对象类型,在这里请大家自行做一个实验,sizeof(int[2])是可以正常运行的,但sizeof int[2]不可以,这就充分证明了int[2]是一个对象类型,因为C语言规定用在sizeof里面括号引导的只能是Type,关于数组的概念,请参看非数组和数组声明。
4、此外,C语言的标准中,数组的核心理念就是只有一维数组,这个概念是学习指针最重要的核心之一。比如int a[2][3],意味着声明了一个对象b,其类型是int[2][3],其含义是2个元素组成的一个一维数组,每个数组的元素是int[3]。只有这样去看待数组,才能去理解C语言的Value核心思想。
5、任何一个Type,都有其对应的一个指针类型,分别称之为Reference Type和Pointer Type,这里需要理解的点有如下几个:1)比如int,其对应的指针类型是int*,2)数组int[2],其对应的指针类型是int(*)[2]。3)对于int*,其对应的指针类型是int**。所以没有多级指,当我们看到int**** p这个语句的时候,这说明声明了一个变量p,其类型是int****,这个指针对应的Reference Type是int***。建立这个概念至关重要,这个部分请参看指针声明。
6、学习指针另一个重要的概念是lvalue,也就是左值,为了理解左值,需要先了解什么是表达式(请参看左值和表达式),理解哪些表达式能够作为lvalue。
7、理解了lvalue之后,下面重要的是理解lvalue的取值规范,比如声明int a;当我们写一个语句a=1;的时候,这个a是lvalue,也是一个modifiable lvalue,所以可以放在等号左边,而当我们写a = a+1的时候,等号左边的a依然是一个lvalue,而等号右边的a也是一个lvalue,但是因为这个a现在是a+1这个更大表达式的子表达式,所以现在就需要取这个a表达式的值,这个过程是lvalue conversion。
8、关于数组名,比如int a[2][3],有很多人说a就是数组的首地址,这个说法是不准确的,a是一个变量名,是一个基础表达式,因此是一个lvalue,a这个表达式自然能也是有值,它的值是这个数组第一个元素的首地址,所以a的返回值是<第一个元素的首地址,int(*)[3]>,这个取值的规范是和之前提到数组必须用一维视角去理解是呼应的。只有理解了这个,才能理解为什么数组作为实参传递,形参中数组第一维大小信息丢了的原因(事实上,这就是pass by value中这个value的含义,请参看理解参数传递),这个部分内容还可以参看一维的视角看数组。
lvalue和取值,先要了解非数组和数组对象不同的内存组织方式非数组对象内存组织和数组对象内存组织。
9、任何表达式(除了放到等号左边被赋值),都有返回值,C语言中 ,所有对象类型的表达式(用exp表示)都有三种潜在的返回值,分别是表达式对应内存的首地址(&exp,如果这个表达式是lvalue的话),sizeof(exp),和exp本身。value是一个核心概念,理解这个概念,才能更好的理解函数中pass by value的含义,这部分内容可以参看观察内存的视角和观察数组的内存。
10、int const是一种合法的对象类型,需要把int const当做一个整体来看待,所以int const也有对应的指针类型,即int const*,为了理解这个内容,可以参看const的用法以及typedef的用法。
非常仓促的做了一些说明,有不尽之处,请多多见谅,并欢迎讨论。视频的整体逻辑并没有事先梳理,所以有一些混乱,也请见谅。