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

一道90%都会做错的指针题
今天,在我们的一个小群里,一个同学发了一道题目给我看,这道题目应该是C语言面试的一股清流了,各种招聘笔试上都可以看到,我试着发到我的大群里去,发现有人对这个理解不是很深刻,所以再发出来,知识总是在不断的碰撞中提高的,同理,球技也是一样。
在这里插入图片描述
在这里插入图片描述
大家可以先猜测一下这两个程序的输出是什么?

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

#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 类型。有点拗口,我们画个图。

在这里插入图片描述
上图中 我们定义了一个变量 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的数组,这个数组是个什么鬼东西,我们知道,内存可以起一个别名,数组是连续几个同类型内存块的别名。

在这里插入图片描述
好了,我们再说下一个问题 ,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 ) 。只能偏移到数组的下一个位置。

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

2,5
2,2

原创: 写代码的篮球球痴 嵌入式Linux
微信可以关注:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值