本节主要对C语言——指针初阶(一)的一些内容进行补充,并主要讲解数组指针。
一.补充(易错点重点)
① 为了表示指针变量和它所指向的变量之间的联系,在程序中用“ * ”符号表示“指向”。若已定义i_pointer为指针变量,则* i_pointer是i_pointer所指向的变量,因此* i_pointer也代表一个变量,它和变量i是同一回事。
下面两个语句作用相同:
(1)i=3;
(2) * i_pointer=3;
第二个语句含义是将3赋给指针变量i_pointer所指向的变量i.
② C语言提供两种有关的运算符:(1)&:取地址运算符(用来表示变量的地址)(2)*:取内容运算符(用来取其指向的内容,或称"间接 访问"运算符,或称指针运算符)两种运算符都是单目运算符,其结合性都为自右向左,优先级别相同。
例如.&a为变量a的地址, *p为指针变量o所指向的内存单元的内容 (即p所指向的变量的值)。
二.数组的指针(重点难点)
一维数组的指针
数组名指的是数组首元素的首地址。当创建数组时,编译器自动为它创建一个内部指针常量,并将数组的基址存储在该指针中。
数组名是编译器为该数组创建的指针常量。数组名是指针常量grade = &grade[2]是无效的
比如grade[]={};
那么grade=&grade[0];
若gptr是一个指针变量 gptr=&grade[0] (gPtr+3)=& Grade[0] + 3*4 ; *(gPtr+3) = grade[3];
即指针+数字=指针+数字* sizeof(所指向的数据类型)
指针+数字=指针+数字* sizeof(所指向的数据类型)
数组名不能++,因为数组名指首元素的地址是常量。
下面我们来区分一下*p++与*(p++)与(*p)++
1. **对于`*p++`和`*(p++)`这两种写法是等价的。 根据运算符优先级,后置自增`++`的优先级高于解引用`*`运算符。所以在`*p++`和`*(p++)`中,先计算`p++`。
p++`是先返回`p`的当前值,然后再将`p`的值(指针的值)加1。之后再对这个返回的(未加1之前的)`p`的值进行解引用操作`*`,所以是先取`p`指向的值,然后`p`本身加1。
例如,假设有`int a[] = {1, 2, 3}; int *p=a;`,当执行`*p++`时,首先返回`*p`(此时`*p`为1),然后`p`指向`a[1]`。
2. **对于`(*p)++`** - 首先,括号改变了运算顺序。先执行`*p`,即解引用`p`,得到`p`所指向的变量的值。 - 然后对这个解引用后的值进行后置自增操作`++`,所以是`p`所指向的值加1,而`p`本身(指针)不变。 - 例如,同样假设有`int a[] = {1, 2, 3}; int *p=a;`,当执行`(*p)++`时,`*p`(此时`*p`为1)的值加1,数组`a`的第一个元素变为2,`p`仍然指向`a[0]`。
二维数组的指针
二维数组名+1=偏移一行
此处可以这样理解,二维数组是一个二级指针,数组名指首行的地址,数组名+1指偏移一行,而*num之后对*num进行加减操作是对列进行变换。
int a[10], *p;
p = a;
*(p+i), p[i], *(a+i) 三者等价
这个图其实和上面那个表格是等价的。
下面来分析一下(*pt)[3]与*pt[3]区别
① (*pt)
表示对指针pt
进行解引用。这意味着pt
是一个指向数组(长度为 3)的指针。 比如有如下代码:
int arr[2][3] = { {1, 2, 3}, {4, 5, 6} };int (*pt)[3];pt = arr;
这里pt
是一个指向包含 3 个整数的数组的指针。(*pt)[3]
这种写法试图访问pt
所指向的数组的第 3 个元素(索引为 2,因为数组索引从 0 开始)。在上面的例子中,(*pt)[0]
就是arr[0][0]
(值为 1),(*pt)[1]
是arr[0][1]
(值为 2),(*pt)[2]
是arr[0][2]
(值为 3)。它的重点在于pt
是指向数组的指针,先解引用得到数组,然后通过索引访问数组中的元素。(*pt)
对pt
进行解引用,此时就相当于得到了pt
所指向的那个包含 3 个整数的数组,也就是arr
的第一行{1, 2, 3}
。可以这样理解,(*pt)
让我们定位到了arr
的第一行,然后[1]
这个索引就从这一行中选取了第二个元素。② *pt[3]
根据运算符优先级,[]
(数组下标)运算符的优先级高于*
(解引用)运算符。所以pt[3]
先进行计算,表示pt
是一个指针数组(有 3 个指针元素),pt[3]
是访问这个指针数组中的第 3 个元素(索引为 2)。 然后再对这个指针进行解引用操作*
。例如: int a = 1, b = 2, c = 3;int *pt[3];pt[0]=&a;pt[1]=&b;pt[2]=&c;
在这里,*pt[3]
(假设合法访问,实际这里访问pt[3]
已经越界了,应该是0 - 2
的索引范围)首先会获取pt
数组中的第 3 个指针元素,然后对这个指针进行解引用。这种写法中pt
是一个指针数组,先通过索引访问数组中的指针,再解引用这个指针。 总结:
(int (*pt)[3]) 数组的地址(数组至少二维) (int *pt[3]) 地址数组(一维数组)本期指针第二节就分享到这里~~~。
往期回顾:
C语言——海龟作图(对之前所有内容复习)-CSDN博客
C语言——指针初阶(一)-CSDN博客
C语言函数递归经典题型——汉诺塔问题_《汉诺塔问题》-CSDN博客
C语言——数组基本知识(二)-CSDN博客
C语言——数组基本知识(一)-CSDN博客
C语言——数组逐元素操作练习-CSDN博客
C语言编程练习:验证哥德巴赫猜想 进制转换 rand函数-CSDN博客
C语言——函数基本知识(三)-CSDN博客
C语言——函数基本知识(二)-CSDN博客
C语言 ——函数基本知识(一)-CSDN博客