C语言入门知识点(9.指针a篇)(超详细)

在这里插入图片描述

  • 这里是say-fall分享,感兴趣欢迎互三
  • 专栏:《C语言入门知识点》、《C语言底层》


  • 在了解指针的各种语法之前,我们先来了解一下指针是什么这个问题。

0. 指针是什么?

听指针的汉语可能会一头雾水,但是就像是数学里面第一次见到函数这个名字一样,函数只是一种对应关系而已;指针其实也很简单,它就是“储存数据的地址名称”

1. 内存和地址

1.1 内存

  • 内存是什么?
    内存其实可以类比我们的驿站或者是库房,当我们取快递的时候,里面的货架就是内存储存数据的地方,叫做内存单元,每个内存单元就是一个字节(Byte),而内存单元这个“货架”上,能放8个比特位(货物)

如图
在这里插入图片描述

  • 这就是内存
  • 而我们的货架上有编号,每个内存单元也有编号,这样就能让我们方便找到货物(数据),这个内存单元的编号,也叫做指针,也叫做地址

如图
在这里插入图片描述

  • 好了,我们现在驱散了对指针名称的阴霾

内存编址

  • 内存编址是咋来的?是和我们创建变量一样一个一个赋值吗?
    其实是这样的:在计算机的CPU(中央处理器)要访问内存的时候,他们之间是有一组地址总线的(真实存在的电线),如果是32位计算机,就有32根地址总线,而二进制的计算机每根线都有两种形态:0,1(电脉冲有无),这样的话一根线有两种情况,那么32根线就有2^32个地址

2. 指针变量与地址

2.1 取地址操作符(&)

我们在创建变量的时候,cpu就会向内存申请一块空间并且编号:

#include <stdio.h>
int main()
{
	int a = 1;
	a = 2;
	return 0;
}

下面我们来调试这个代码

创建变量前
在这里插入图片描述

创建变量后
在这里插入图片描述

修改值后
在这里插入图片描述

通过调试,我们也能看到这个a值所储存的地址
在这里插入图片描述

通过上面的指令我们能看到,在a的修改过程中,a的地址是不变的。
在这里插入图片描述

而且通过调试能看到 a 的类型和 &a 的类型,那么有人可能会想到:明明这个int是一个4个字节的类型,一个内存单元对应的是一个字节也就是一个地址,难道不应该返回四个地址吗?

实际上,编译器所返回的地址是四个内存单元中第一个内存单元的地址,也就是这样
在这里插入图片描述

在了解完这个问题以后,我们能看到 &a 的类型为 int *

  • 那我们就来正式介绍一下 & 这个符号
    之前在了解scanf函数的时候,语法规则是这样的:scanf(“%[字母]”,&[上面定义的变量]),并且字母是要和 [上面定义的变量] 类型相对应的,在前文介绍scanf函数的时候提到过:

注意:后面的&[变量],&是取地址操作符,当后面的变量是指针变量(如字符串变量)时,不需要加&。
在这里也是一样, & 为取地址操作符,是把变量的地址取出反映出来的符号
例如:
在这里插入图片描述

这里就是把这个地址放到%d里面去了

2.2 指针变量和解引用操作符(*)

2.2.1 指针变量

在注意中我们也看到了指针变量这四个字,那么什么是指针变量?其实就是我们在取地址以后(&a),将这个&a放到了一个变量中,这个变量就被称作指针变量
前文中提到:通过调试能看到 a 的类型和 &a 的类型
这个&a的类型就是指针变量的类型,在这里是int *
对于&ch(ch为char类型)来说,就是char *
其他类型变量同理。

2.2.2 解引用操作符(*)

在此之前我们从来没有使用过解引用操作符(),除非你把他当作是乘号(
我们刚才把&a储存起来了,并且放到了一个变量里面,这个变量的类型是int *,把他存起来有什么用呢?有什么办法可以把它调用出来吗?
有的有的,就是使用解引用操作符,下面我们看一个的代码:

int main()
{
	int a = 20;
	int * pa = &a;
	printf("%d\n", *pa);
	*pa = 10;
	printf("%d\n", *pa);
	return 0;
}

先看运行结果,然后我们来一步一步细看

在这里插入图片描述

  • 1.创建变量
  • 2.将地址储存在一个叫pa,类型为int *的指针变量里
  • 3.打印 *pa,值为20
    等等, * pa是什么?我们怎么没见过
    这就是解引用操作符, * + 指针变量名称就相当于是该地址所储存的数据
    既然了解完 * pa了,我们继续往下看
    1. *pa = 10
    1. 打印*pa,值为10
      也就是说,在这个代码里,*pa操作目标变量的效果完全地等价于a操作目标变量的效果。

2.3 指针变量的大小

每一种变量类型都有自己的空间大小,比如说int占4个字节,char占一个字节,那指针变量类型占多少内存空间?
下面我们来实操一下:

int main()
{
	printf("%zd\n", sizeof(char*));
	printf("%zd\n", sizeof(short*));
	printf("%zd\n", sizeof(int*));
	printf("%zd\n", sizeof(double*));
	return 0;
}

找不同游戏
在这里插入图片描述
在这里插入图片描述

  • 我们可以发现所有的运行结果都是4,或者8,那为什么两次的运行结果不同呢?
    仔细观察发现上面是在64位环境下运行的,而下面是在32位环境下运行的,那这为什么会导致指针类型所占空间大小改变呢?
  • 前文我们说过内存编制的问题:

内存编址是咋来的?是和我们创建变量一样一个一个赋值吗?
其实是这样的:在计算机的CPU(中央处理器)要访问内存的时候,他们之间是有一组地址总线的(真实存在的电线),如果是32位计算机,就有32根地址总线,而二进制的计算机每根线都有两种形态:0,1(电脉冲有无),这样的话一根线有两种情况,那么32根线就有2^32个地址

  • 这里正是这个原因
    一根线就是一个二进制数位,那么32个二进制数位就是32个bit也就是4个字节。同理64个二进制数位就是8个字节,这样的话,上面的问题就有了答案。
    那我们得到结论:
  • 指针变量的⼤⼩取决于地址的⼤⼩
  • 32位平台下地址是32个bit位(即4个字节)
  • 64位平台下地址是64个bit位(即8个字节)

3. 指针变量类型的意义

3.1指针的解引用与指针变量大小的意义

先来看两段不同代码及其运行结果

  • 1.第一段
int main()
{
	int n = 0x11223344;
	int* pi = &n;
	*pi = 0;
	return 0;
}

在这里插入图片描述在这里插入图片描述

  • 2.第二段
int main()
{
	int n = 0x11223344;
	char* pc = (char*)&n;
	*pc = 0;
	return 0;
}

在这里插入图片描述
在这里插入图片描述

能看得出来在*pc=0的时候第一段代码修改了4个字节的值,全部修改为0,但是第二段代码只修改了1个字节。
这证明指针变量大小虽然相同,但是也是有一些不一样的地方的。

本节完

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值