第五章 指针
INIT

INIT:本节内容正式开始。action!
一、关于内存那点事
存储器:存储数据器件
外存
外存又叫外部存储器,长期存放数据,掉电不丢失数据
常见的外存设备:硬盘、flash、rom、u盘、光盘、磁带
内存
内存又叫内部存储器,暂时存放数据,掉电数据丢失
常见的内存设备:ram、DDR
物理内存:实实在在存在的存储设备
虚拟内存:操作系统虚拟出来的内存,当一个进程被创建的时候,或者程序运行的时候都会
分配虚拟内存,虚拟内存和物理内存之间存在映射关系。
操作系统会在物理内存和虚拟内存之间做映射。
在32位系统下,每个进程(运行着的程序)的寻址范围是4G,0x00 00 00 00 ~0xff ff ff ff
在写应用程序的,咱们看到的都是虚拟地址。
在运行程序的时候,操作系统会将 虚拟内存进行分区。
1.堆
在动态申请内存的时候,在堆里开辟内存。
2.栈
主要存放局部变量(在函数内部,或复合语句内部定义的变量)。
3.静态全局区
1):未初始化的静态全局区
静态变量(定义的时候,前面加static修饰),或全局变量 ,没有初始化的,存在此区
2):初始化的静态全局区
全局变量、静态变量,赋过初值的,存放在此区
4.代码区
存放咱们的程序代码
5.文字常量区
存放常量的。
内存以字节为单位来存储数据的,咱们可以将程序中的虚拟寻址空间,看成一个很大的一维的字符数组
本章所接触的内容,涉及到的内存都是虚拟内存,更准确来说是虚拟内存的用户空间
二、指针的相关概念
操作系统给每个存储单元分配了一个编号,从0x00 00 00 00 ~0xff ff ff ff
这个编号咱们称之为地址。
指针就是地址。

指针变量:是个变量,是个指针变量,即这个变量用来存放一个地址编号
在32位平台下,地址总线是32位的,所以地址是32位编号,所以指针变量是32位的即4个字节。
注意:
1:无论什么类型的地址,都是存储单元的编号,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节大小
2:对应类型的指针变量,只能存放对应类型的变量的地址
举例:整型的指针变量,只能存放整型变量的地址
扩展:
字符变量 char ch; ch占1个字节,它有一个地址编号,这个地址编号就是ch的地址
整型变量 int a; a占4个字节,它占有4个字节的存储单元,有4个地址编号。

Int a=0x00 00 23 4f
三、指针的定义方法
1.简单的指针
数据类型 * 指针变量名;
int * p;
//定义了一个指针变量p
在 定义指针变量的时候 * 是用来修饰变量的,说明变量p是个指针变量。
变量名是 p
2.关于指针的运算符
& 取地址 、 *取值
&:获取一个变量的地址
*:在定义一个指针变量时,起到标识作用,标识定义的是一个指针变量
除此之外其他地方都表示获取一个指针变量保存的地址里面的内容

#include <stdio.h>
int main(int argc, char *argv[])
{
//定义一个普通变量
int a = 100;
//定义一个指针变量
int *p;
//给指针变量赋值
//将a的地址保存在p中
p = &a;
printf("a = %d %d\n", a, *p);
printf("&a = %p %p\n", &a, p);
return 0;
}
执行结果
a = 100 100
&a = 0029FEA8 0029FEA8
扩展:如果在一行中定义多个指针变量,每个指针变量前面都需要加*来修饰
int *p,*q;
//定义了两个整型的指针变量p和q
int * p,q;
//定义了一个整型指针变量p,和整型的变量q
3、指针大小
在32位系统下,所有类型的指针都是4个字节。
因为不管地址内的空间多大,但是地址编号的长度是一样的,所以在32位操作系统中,地址都是四个字节。
#include <stdio.h>
int main(int argc, char *argv[])
{
char *a;
short *b;
int *c;
long *d;
float *e;
double *f;
printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(b) = %d\n", sizeof(b));
printf("sizeof(c) = %d\n", sizeof(c));
printf("sizeof(d) = %d\n", sizeof(d));
printf("sizeof(e) = %d\n", sizeof(e));
printf("sizeof(f) = %d\n", sizeof(f));
return 0;
}
执行结果
sizeof(a) = 4
sizeof(b) = 4
sizeof(c) = 4
sizeof(d) = 4
sizeof(e) = 4
sizeof(f) = 4
四、指针的分类
按指针指向的数据的类型来分。
1:字符指针
字符型数据的地址
char *p;
//定义了一个字符指针变量,只能存放字符型数据的地址编号
char ch;
p= &ch;
2:短整型指针
short int *p;
//定义了一个短整型的指针变量p,只能存放短整型变量的地址
short int a;
p =&a;
3:整型指针
int *p;
//定义了一个整型的指针变量p,只能存放整型变量的地址
int a;
p =&a;
注:多字节变量,占多个存储单元,每个存储单元都有地址编号,
c语言规定,存储单元编号最小的那个编号,是多字节变量的地址编号。
4:长整型指针
long int *p;
//定义了一个长整型的指针变量p,只能存放长整型变量的地址
long int a;
p =&a;
5:float 型的指针
float *p;
//定义了一个float型的指针变量p,只能存放float型变量的地址
float a;
p =&a;
6:double型的指针
double *p;
//定义了一个double型的指针变量p,只能存放double型变量的地址
double a;
p =&a;
7:函数指针
8、结构体指针
9、指针的指针
10、数组指针
总结:无论什么类型的指针变量,在32位系统下,都是4个字节,只能存放对应类型的变量的地址编号。
五、指针和变量的关系
指针可以存放变量的地址编号
在程序中,引用变量的方法
1:直接通过变量的名称
int a;
a = 100;
2:可以通过指针变量来引用变量
int * p;
//在定义的时候,*不是取值的意思,而是修饰的意思,修饰p是个指针变量
p = &a;
//取a的地址给p赋值,p保存了a的地址,也可以说p指向了a
*p = 100;
//在调用的时候*是取值的意思,*指针变量 等价于指针指向的变量
注:指针变量在定义的时候可以初始化
int a;
int * p = &a;
//用a的地址,给p赋值,因为p是指针变量
指针就是用来存放变量的地址的。
*+指针变量 就相当于指针指向的变量
指针变量只能保存开辟好空间的地址,不能随意保存地址
#include <stdio.h>
int main(int argc, char *argv[])
{
int *p1,*p2,temp,a,b;
p1=&a;
p2=&b;
printf("请输入:a b的值:\n");
scanf("%d %d", p1, p2); //给p1和p2指向的变量赋值
temp = *p1; //用p1指向的变量(a)给temp赋值
*p1 = *p2; //用p2指向的变量(b)给p1指向的变量(a)赋值
*p2 = temp; //temp给p2指向的变量(b)赋值
printf("a=%d b=%d\n",a,b);
printf("*p1=%d *p2=%d\n",*p1,*p2);
return 0;
}
执行结果
请输入:a b的值:
70 90
a=90 b=70
*p1=90 *p2=70
扩展:
对应类型的指针,只能保存对应类型数据的地址,
如果想让不同类型的指针相互赋值的时候,需要强制类型转换。
#include <stdio.h>
int main(int argc, char *argv[])
{
int a=0x1234,b=0x5678;
char *p1,*p2;
printf("%#x %#x\n",a,b);
p1=(char *)&a;
p2=(char *)&b;
printf("%#x %#x\n",*p1,*p2);
p1++;
p2++;
printf("%#x %#x\n",*p1,*p2);
return 0;
}
END
END:本节内容到此结束。
个人提升之余,别忘了和小伙伴积极交流,很多人觉得他们在思考,而实际上他们只是在重新整理自己的偏见。请珍惜和他人交流讨论的机会。

希望你每一天都有所收获,进步up up up。今天的我们并不比昨天更聪明,但一定要比昨天更睿智。

彩蛋🎁
如果你来访我,我不在,请和我门外的花坐一会儿,它们很温暖,我注视它们很多日子了。
- 汪曾祺《人间草木》
恭喜你🎉,完成了对第五章《指针》部分的学习,下一章我们将学习动态内存申请。
⏩第六章 《动态内存申请》