
- 这里是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了,我们继续往下看 -
- *pa = 10
-
- 打印*pa,值为10
也就是说,在这个代码里,*pa操作目标变量的效果完全地等价于a操作目标变量的效果。
- 打印*pa,值为10
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个字节。
这证明指针变量大小虽然相同,但是也是有一些不一样的地方的。
本节完










66万+

被折叠的 条评论
为什么被折叠?



