讲到指针和数组,先给大家看一道例题:
题目:填空练习(指向指针的指针)
1.程序分析:
2.程序源代码:
main()
{ char *s[]={"man","woman","girl","boy","sister"};
char **q;
int k;
for(k=0;k<5;k++)
{ ;/*这里填写什么语句*/
printf("%s\n",*q);
}
}
指向指针的指针是什么呢?我们把一个指向指针变量的指针变量,成为多级指针变量,char **p;这种。
我们再看这道题 char *s[]={"man","woman","girl","boy","sister"};这时一个字符串数组,为什么存放字符串的数组要定义成指针数组呢?我们先来看看指针数组是什么
指针数组的实质还是数组,是存放指针的数组int *p[] ,(int *)p[]是数组指针,指向数组地址的指针,这两个概念好像很绕是吧,很难分辨,在这里,博主将自己记忆的方法告诉大家,int *p[] 大家可以根据运算符优先级来记忆,[]的优先级 > *的优先级,所以这首先是个数组,然后才是指针,所以是指针数组;(int *)p[],()和[]优先级相等,但()是左结合,所以(int *)p[]先是指针,后是数组,所以这是个数组指针。
回到这一题,看这一句printf("%s\n",*q);我们知道%s后面跟的应该是一个地址,而*p是p中所指的数据,所以p地址中保存的还是一个地址,这就是多级指针,而我们用char **q;我们只知道q所指向的首地址,后面的数据如何分配,我们不得而知,所以这道题应该怎么做呢?
大家看看我们添加的内容:
#include <stdio.h> int main() { char *s[]={"man","woman","girl","boy","sister"}; char **q; int k; for(k = 0;k < 5;k++) { q = &s[k]; printf("%s\n",*q); } }
大家看输出结果:
fs@ubuntu:~/qiang/shuzu$ gcc -o shuzu5 shuzu5.c fs@ubuntu:~/qiang/shuzu$ ./shuzu5 man woman girl boy sister fs@ubuntu:~/qiang/shuzu$
为什么我们给的是p = &s[k]而不是*p = &s[k]呢?这里我们应该先理解二维数组
提到二维数组,我们又不得不提一维数组,一维数组 int a[n] 这里int是我们数据元素的数据类型,a是什么,a是数组名,代表数组的首地址,是数组第一个元素的地址,也就是可以说,a是int a[n]的地址,a[0]也是;这里记住a是地址常量,是常量!常量!常量!重要的事说三遍!常量的特性是什么,不能对其赋值,大家记住这一点!"[]"是变址运算符,所以*(a+i)和a[i]无条件等价!n是数据的偏移量,是数据的偏移量,而不是字节的偏移量!这点和指针的*p++一样,是数据的偏移量,因为我们数组里放的是整型数据,也可能是字符型数据,所占字节大小是不一样的,所以是数据的偏移量!
我们回到二维数组 以int [3][4]为例,如下图
我们知道a[3]中a是地址,a[3][4]呢?a这里也是地址,存放的是什么数据呢?看图就知道,存放的是a[0] a[1] a[3],而a[0] a[1] a[2]是什么呢?其实是地址,地址里指向的分别是a[0][0] a[1][0] a[2][0]的数据,那我们是不是也可以将二维数据当成一个二级指针来看呢?大家思考一下。
博主思考了一下,说a里面存放的是a[0] a[1] a[2]的地址不太确切 ,但a[0] a[1] a[2]在这里确实是地址 ,上面说到二维数组是否可以看成二级指针,当然不能这样看,大家应该知道,a确实是代表地址,但它与指针有什么区别呢?大家看a[1] 的地址如何表示呢?是a+1,指针怎么表示呢?是p+1,好像是一样哦,但大家应该明白这里 a 是常量 ,p是变量,a + 1 中 a 的值没有发生变化,数组里面所有数据的地址都是由唯一的常量 a 来确定的! 而p + 1, p 的值已经发生了变化,因为 p 是变量!!!!!
我们再看看char *s[]={"man","woman","girl","boy","sister"},为什么要加*呢?因为存放的是字符串啊。字符串用地址来表示的啊!所以二级指针 二维数组 指针数组 这几个概念有时很容易把人搞晕,大家一定要注意分辨!
今天先写到这,后面会指针数组的深入内容!