一道90%都会做错的指针题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weiqifa0/article/details/102559314

今天,在我们的一个小群里,一个同学发了一道题目给我看,这道题目应该是C语言面试的一股清流了,各种招聘笔试上都可以看到,我试着发到我的大群里去,发现有人对这个理解不是很深刻,所以再发出来,知识总是在不断的碰撞中提高的,同理,球技也是一样。

640?wx_fmt=png640?wx_fmt=png

大家可以先猜测一下这两个程序的输出是什么?

什么是指针?

书籍看得比较多了,这个指针那个指针,但是我认为如果说到指针,不说变量,就有点耍流氓,所以我认为理解指针的基础就要理解它是一个变量,所以指针,可以理解为指针变量,再延伸出来,就是地址变量,可以存地址的一个变量,而且存的这个地址指向的类型也是有要求的

#include "stdio.h"	

	
int main()	
{	
    int i = 12; 	
    int *p = &i;	
    printf("%d\n",sizeof(int *));	
    printf("%d\n",sizeof(p));	
    printf("%p\n",&p);	
}

看上面的代码,p是一个指针变量,p存的是一个地址,p存的这个地址存的类型是 int 类型。有点拗口,我们画个图。640?wx_fmt=png

上图中 我们定义了一个变量 p ,所以编译器就必须要给这个p分配内存,如上图所示,这个p的内存是 0x1000,p是什么类型呢?从定义可以看,p的类型是 int *,所以说p只可以存 int * 类型的值,也就是一级指针,就是一级地址,也就是 i 的地址。

i 也是一个变量,这个变量的地址是 0x1001, 这个地址上存的值是 12。

地址本来是没有名字的,因为定义了变量,所以地址就对应有了一个别名,这个名字就代表了这个内存地址

弱弱问一句,声明有没有分配内存呢?

什么是数组?

我觉得指针和数组是不用比较的,我们比较的是指针变量和数组名,这两个东西才有比较的意义,数组是一类数据的集合,指针变量只能是一个地址变量,没必要折腾自己的大脑了。

#include "stdio.h"	

	
int main()	
{	
    int array[5] = {1,2,3,4,5}; 	
    return (0);	
}

我们定义了一个 array的数组,这个数组是个什么鬼东西,我们知道,内存可以起一个别名,数组是连续几个同类型内存块的别名

640?wx_fmt=png

好了,我们再说下一个问题 ,array 是数组的名字,&array 获取的是这个数组的地址,而且这个地址的值等于 &array[0] 「首元素的地址」。

虽然数值相等,但是他们的含义是不一样的。

如果 &array +1 这个时候,地址偏移的是 &array + sizeof(array)

如果 &array[0] +1 这个地址偏移是 &array[0] + sizeof(array[0]) ,也就是偏移到地址 &array[1]上。

再看看上面的两个题目

我们再看看上面的题目

int *p = (int*)(&a +1);

这句代码执行后,p的值应该是 &a +sizeof(a)了。

但是下面这句代码就不一样了。

#include "stdio.h"	

	
int main()	
{	
    int a[5] = {1,2,3,4,5};     	
    int *p = &a;	
    int *q = a;	
    printf("%d %d\n",*(q+1),*(p+1)); 	
    return (0);	
}

&a 赋值给 p 后,这个意义就不一样了,这时候,它的类型是 int* ,p+1 就是 p + sizeof(int *) 。只能偏移到数组的下一个位置。

640?wx_fmt=png

所以这样说之后,大家都知道上面的输出结果了吗?

2,5

2,2


640?wx_fmt=jpeg

640?wx_fmt=png

扫码或长按关注

回复「 加群 」进入技术群聊

猜你喜欢

转载自blog.csdn.net/weiqifa0/article/details/102559314