一、指针是什么?
指针是什么?
指针理解的2个要点:
1、指针是内存中一个最小单元(内存单元)的编号,也就是地址
2、平时口语中说的指针,通常是指针变量,用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量
那么我们就这样理解:内存
指针变量
我们可以通过&(取地址操作符)取出变量的内存地址,把地址可以存放到一个变量中,这个变量就是指针变量
int main()
{
int a = 10; // a是整型变量,占用4个字节的内存空间
int* p = &a;
return 0;
}
总结
指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)
那这里的问题是:
- 一个小的单元到底是多大?(1个字节)
- 如何编址?
- 经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电
(低电压)就是(1或者0);
那么32根地址线产生的地址就会是:
这里就有2的32次方个地址:
同样的方法,那64位机器,如果给64根地址线,那能编址多大空间,自己计算。
这里我们就明白:
- 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
- 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
总结:
- 指针变量是用来存放地址的,地址是唯一标示一块地址空间的。
- 指针的大小在32位平台是4个字节,在64位平台是8个字节
// #64位平台
char* pc = NULL;
short* ps = NULL;
int* pi = NULL;
double* pd = NULL;
// sizeof 返回的类型是无符号整型
printf("%zu\n", sizeof(pc));
printf("%zu\n", sizeof(ps));
printf("%zu\n", sizeof(pi));
printf("%zu\n", sizeof(pd)); //8
zu是sizeof的标配
二、指针和指针类型
这里我们在讨论一下:指针的类型
我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?
准确的说:有的。
2.1 指针类型的第1个意义
当有这样的代码:
int a = 0x11223344;
char* pc = (char*)&a;
*pc = 0;
结论1
指针类型决定了指针在被解引用的时候访问几个字节
如果是 int 的指针,解引用访问4个字节
如果是 char 的指针,解引用访问1个字节
推广到其他类型等等
2.2 指针类型的第2个意义
int n = 10;
char* pc = (char*)&n;
int* pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
结论2:
指针的类型决定了指针+-1操作的时候,跳过几个字节//决定了指针的步长,也就是说指针的类型决定了指针向前或向后走一步有多大距离比如char类型的指针+1,只跳过了一个字节
如果是int类型的指针,则跳过了4个字节
如果类型不匹配,强制类型转换即可
int *和 float *是不是就可以通用啊?
不能通用! int*
和 float*
是完全不同的类型,不可以随意互换使用。
主要原因:
1. 指向的数据类型不同
int*
指向整数(通常4字节)float*
指向浮点数(通常4字节)
2. 内存解释方式不同 虽然都可能占用4字节,但存储格式完全不同:
int
: 二进制补码表示float
: IEEE 754浮点格式
3. 编译器类型检查
int a = 10;
float b = 3.14f;
int* p1 = &a;
float* p2 = &b;
p1 = p2; // 编译错误!类型不匹配
4. 强制转换的后果
int x = 1065353216;
float* fp = (float*)&x;
printf("%f\n", *fp); // 输出 1.000000(不是期望的整数值)
正确做法:
- 使用
void*
作为通用指针 - 需要时进行适当的类型转换
- 或者使用联合体(union)处理同一内存的不同解释
所以 int*
和 float*
绝对不能通用!
2.3 容易混淆的点
pa的空间大小与a的空间大小没有半毛钱关系
三、野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1 野指针成因
1、指针未初始化
int* p;
// p没有初始化,就意味着没有明确的指向
// 一个局部变量不初始化,放的是随机值;0xcccccccc
*p = 10;
- p没有初始化,就意味着没有明确的指向
- 一个局部变量不初始化,放的是随机值;0xcccccccc
- 非法访问内存
2、指针越界访问
本网站原创文章版权归何大锤的狂飙日记所有。发布者:何大锤,转转请注明出处:何大锤的博客