关于数组与指针的问题,常见的有,指向数组的指针,声明数组指针和指针数组等,在这里主要看看指向数组的指针是怎么回事。
指向数组的指针,总的来说,实际上可以归纳为如下几点:
1、 有一个一维数组int a1[10],定义一个指针,指向一维数组名。
2、 有一个一维数组int a2[10],定义一个指针,指向一维数组名的地址。
3、 有一个二维数组int a3[3][4],定义一个指针,指向二维数组名。
4、 有一个二维数组int a4[3][4],定义一个指针,指向二维数组名的地址。
这四个问题,都是让我们定义一个指针,指向一片连续的内存空间,只是说这片内存空间有的是一维,有的是二维而已。
我们这次先分析下前面两道题:
那我们先看第一个题目,因为a1本身就是连续空间的首地址,那么我们就只需要定义一个地址变量p,让p = a就可以了,既然要用“=”,那么等号两边就需要的类型一样,所以毫无疑问,p应该为 <数据类型> *p了。现在不确定的就是数据类型了。根据指针的定义,应该有p[0]到p[1]的偏移和a[0]到a[1]的偏移一致,我们很容易看出,a[0]和a[1]的偏移是int类型。那么对于第一个题目的数据类型就应该为int了,第一题的答案为int *p;
接着看第二问题,这个问题的难点在,什么叫数组名的地址,我们都知道C语言中的变量都有地址,但数组名是什么,他是不是也在内存中实实在在的存在哪,回答是否定的(感兴趣的同学,可以试着证明下,a的值和&a的值有什么特点)。a是数组空间的一个标号,那对标号取地址,是什么那,我们可以试着把&a和&a+1的地址都打印出来,然后看下他们的关系,我们会发现,&a和&a+1之间的偏移实际上是10个int的单位。那么我们也可以推出数组名的地址原来标示了整个数组的空间。也就是说&a[0]和&a[1]的偏移实际上是一个int [10]的空间。那么对于<数据类型> *p来说,数据类型就是指int [10]这个空间了。第二题的答案为int (*p)[10];
对于前2个问题,可以写出如下实验代码:
int main(int argc,char *argv[])
{
int a1[10];
int *p;
int (*p1)[10];
printf(“the address of a1[0] is %p,the address of a1[1] is %p\n”,&a1[0],&a1[1]);
printf(“the &a1[0] is %p,the &a[1] is %p\n”,&(&a1)[0],&(&a1)[1]);
p = a1;
p1 = &a1;
}
以上程序中p1,p即我们应该填的,如果编译器编译时没有警告,那么说明我们的这样写法是正确的。
那么在深入下的分析下,p1和p现在都要他访问a1中的第二个元素,即a1[1],应该怎么做那?
大家可以思考下,答案是:p[1] p1[0][1],如何验证那,只要执行if(p[1] = = p1[0][1]),如果这个逻辑为真,那说明正确。
上次题目的内容为:
1、 有一个一维数组int a1[10],定义一个指针,指向一维数组名。
2、 有一个一维数组int a2[10],定义一个指针,指向一维数组名的地址。
3、 有一个二维数组int a3[3][4],定义一个指针,指向二维数组名。
4、 有一个二维数组int a4[3][4],定义一个指针,指向二维数组名的地址。
还记得前2道题的分析方法吗,第一个题,应该定义一个int *p的指针来指向一维数组a1(这个是比较简单的)。而第二个题目为定义int (*p)[10]来指向一维数组a2的地址。
我们分析后面面两道题:
int a3[3][4]为二维数组,大家都知道他的物理意义是3行4列,但是我们都知道,计算机的内存是一维空间,即不可能按照一个面的方式存储二维数组的,那么计算机怎么存储呢,大家可以参考下C语言教材,二维数组是按照从上到下从左到右的顺序放置到一维内存空间的。
比如int a3[3][4] = {{1,2,3,4},{5,6,7,8}},在计算机分配了8个int空间按顺序存储1,2,3,4,5,6,7,8,那计算机怎么知道1,2,3,4为第一行那,而不是1,2为一行,3,4为一行那。看来a3中的“[4]”起到了很重要的作用。
那么我们还是回到题目上,定义一个指针指向a3,那么我们就先看下a3是怎么读内存的?a3 和a3+1,我们分别用%p来查看下他们的地址偏移,程序大家可以自己写,我们会发现他们两者的差值为16,我们又知道a3里面存着都是4个字节的int类型,那么可以知道,从a3到a3+1偏移了4个int单位,而这个4恰好是第二个方括号的数字。
那么我们定义的指针P偏移内存的方式也应该是4个int单位才能和a3匹配,所以很多同学在面试时给出int **p的结果是不对的,因为二维指针的偏移还是4个字节为一个偏移单位,跟我们分析的不一样。那我们如果去写一个指向4个int单位的指针那,大家可以考虑下使用小括号来帮助我们理解。
答案为:int (*p)[4]。看到这个答案,和我们的第二题的答案很类似,所以我们可以这样认为,一维数组名的地址实质就是一个二维数组的一行。
下面我们看第四题,有涉及到数组名的地址的问题,二维数组名的地址,根据我们上次分析,可以知道,二维数组名的地址偏移实际上是一个二维数组对象,即偏移一个面,那么对于指针的定义,应该容易的得到:
int (*p)[3][4];
这样的答案。
综合这几道题目,我们能更深入的理解关于指针的含义了。
指向数组的指针,总的来说,实际上可以归纳为如下几点:
1、 有一个一维数组int a1[10],定义一个指针,指向一维数组名。
2、 有一个一维数组int a2[10],定义一个指针,指向一维数组名的地址。
3、 有一个二维数组int a3[3][4],定义一个指针,指向二维数组名。
4、 有一个二维数组int a4[3][4],定义一个指针,指向二维数组名的地址。
这四个问题,都是让我们定义一个指针,指向一片连续的内存空间,只是说这片内存空间有的是一维,有的是二维而已。
我们这次先分析下前面两道题:
那我们先看第一个题目,因为a1本身就是连续空间的首地址,那么我们就只需要定义一个地址变量p,让p = a就可以了,既然要用“=”,那么等号两边就需要的类型一样,所以毫无疑问,p应该为 <数据类型> *p了。现在不确定的就是数据类型了。根据指针的定义,应该有p[0]到p[1]的偏移和a[0]到a[1]的偏移一致,我们很容易看出,a[0]和a[1]的偏移是int类型。那么对于第一个题目的数据类型就应该为int了,第一题的答案为int *p;
接着看第二问题,这个问题的难点在,什么叫数组名的地址,我们都知道C语言中的变量都有地址,但数组名是什么,他是不是也在内存中实实在在的存在哪,回答是否定的(感兴趣的同学,可以试着证明下,a的值和&a的值有什么特点)。a是数组空间的一个标号,那对标号取地址,是什么那,我们可以试着把&a和&a+1的地址都打印出来,然后看下他们的关系,我们会发现,&a和&a+1之间的偏移实际上是10个int的单位。那么我们也可以推出数组名的地址原来标示了整个数组的空间。也就是说&a[0]和&a[1]的偏移实际上是一个int [10]的空间。那么对于<数据类型> *p来说,数据类型就是指int [10]这个空间了。第二题的答案为int (*p)[10];
对于前2个问题,可以写出如下实验代码:
int main(int argc,char *argv[])
{
int a1[10];
int *p;
int (*p1)[10];
printf(“the address of a1[0] is %p,the address of a1[1] is %p\n”,&a1[0],&a1[1]);
printf(“the &a1[0] is %p,the &a[1] is %p\n”,&(&a1)[0],&(&a1)[1]);
p = a1;
p1 = &a1;
}
以上程序中p1,p即我们应该填的,如果编译器编译时没有警告,那么说明我们的这样写法是正确的。
那么在深入下的分析下,p1和p现在都要他访问a1中的第二个元素,即a1[1],应该怎么做那?
大家可以思考下,答案是:p[1] p1[0][1],如何验证那,只要执行if(p[1] = = p1[0][1]),如果这个逻辑为真,那说明正确。
上次题目的内容为:
1、 有一个一维数组int a1[10],定义一个指针,指向一维数组名。
2、 有一个一维数组int a2[10],定义一个指针,指向一维数组名的地址。
3、 有一个二维数组int a3[3][4],定义一个指针,指向二维数组名。
4、 有一个二维数组int a4[3][4],定义一个指针,指向二维数组名的地址。
还记得前2道题的分析方法吗,第一个题,应该定义一个int *p的指针来指向一维数组a1(这个是比较简单的)。而第二个题目为定义int (*p)[10]来指向一维数组a2的地址。
我们分析后面面两道题:
int a3[3][4]为二维数组,大家都知道他的物理意义是3行4列,但是我们都知道,计算机的内存是一维空间,即不可能按照一个面的方式存储二维数组的,那么计算机怎么存储呢,大家可以参考下C语言教材,二维数组是按照从上到下从左到右的顺序放置到一维内存空间的。
比如int a3[3][4] = {{1,2,3,4},{5,6,7,8}},在计算机分配了8个int空间按顺序存储1,2,3,4,5,6,7,8,那计算机怎么知道1,2,3,4为第一行那,而不是1,2为一行,3,4为一行那。看来a3中的“[4]”起到了很重要的作用。
那么我们还是回到题目上,定义一个指针指向a3,那么我们就先看下a3是怎么读内存的?a3 和a3+1,我们分别用%p来查看下他们的地址偏移,程序大家可以自己写,我们会发现他们两者的差值为16,我们又知道a3里面存着都是4个字节的int类型,那么可以知道,从a3到a3+1偏移了4个int单位,而这个4恰好是第二个方括号的数字。
那么我们定义的指针P偏移内存的方式也应该是4个int单位才能和a3匹配,所以很多同学在面试时给出int **p的结果是不对的,因为二维指针的偏移还是4个字节为一个偏移单位,跟我们分析的不一样。那我们如果去写一个指向4个int单位的指针那,大家可以考虑下使用小括号来帮助我们理解。
答案为:int (*p)[4]。看到这个答案,和我们的第二题的答案很类似,所以我们可以这样认为,一维数组名的地址实质就是一个二维数组的一行。
下面我们看第四题,有涉及到数组名的地址的问题,二维数组名的地址,根据我们上次分析,可以知道,二维数组名的地址偏移实际上是一个二维数组对象,即偏移一个面,那么对于指针的定义,应该容易的得到:
int (*p)[3][4];
这样的答案。
综合这几道题目,我们能更深入的理解关于指针的含义了。