🍁收录专栏:C语言——探索高效编程的基石
🍁 如果觉得博主的文章还不错的话,请点赞👍收藏🌟 三连支持一下博主💞
一、指针是什么?
在计算机科学中,指针是一种变量类型,它存储了一个内存地址。这个内存地址指向计算机内存中的一个特定位置,该位置存储了实际的数据。通过使用指针,可以直接访问和修改存储在特定内存位置的数据,而无需复制或移动数据本身。(本质上指针就是地址)
1.1指针与内存间的关系
这里我们知道char类型占1个字节的内存空间,short类型占2个字节的内存空间,int类型占4个字节的内存空间,long类型占4个字节的内存空间,long long类型占8个字节的内存空间,float类型占4个字节的内存空间,double类型占8个字节的内存空间。
内存
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);
那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
........
01111111 11111111 11111111 11111111
10000000 00000000 00000000 00000000
10000000 00000000 00000000 00000001
........
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111
一共有种可能的编号,每一种编号表示一个内存单元的地址,所以共有个地址。每个地址表示一个字节,那我们就可以给
(2^32Byte=2^32/1024KB=2^32/1024/1024MB=2^32/1024/1024/1024GB = 4GB)4G的空闲进行编址。
同样的方法,那64位机器,如果给64根地址线,那么就有个地址。
这里我们就明白:
🌴 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储(因为一个字节等于八个比特位,而一个0或1占一个比特位),所以一个指针变量的大小就应该是4个字节。
🌴同理,那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
1.2指针变量存放地址
注意:这里a的值以16进制的形式存储在内存中的并且是倒着存放的(这里涉及到大小端问题) 。
总结:指针变量是用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
二、指针和指针类型
2.1指针有哪些类型?
char *pc = NULL; int *pi = NULL; short *ps = NULL; long *pl = NULL; float *pf = NULL; double *pd = NULL;
不同类型的指针其实是为了存放对应类型变量的地址。
2.2指针类型的意义是什么?
2.2.1指针的类型决定了指针向前或者向后走一步有多大(距离)。
这里我们不难看出,char*类型的指针加一时,它的地址增加了1个字节,而int*类型的指针加一时,它的地址增加了4个字节 。
总结:指针变量加减 ,跳过多少字节(地址加减多少)取决于指针类型
例如:
如果是 char 类型指针,指针变量加 1或减1 实际上地址加了或减了 1 个字节
如果是 short 类型指针,指针变量加 1或减1 实际上地址加了或减了 2 个字节
如果是 int 类型指针,指针变量加 1或减1 实际上地址加了或减了 4 个字节
2.2.2 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
📌char*指针
这里是将int类型的变量n的地址强制转换赋给了char类型指针pc
指针pc解引用后:
📌int*指针
指针pi解引用后:
三、野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1野指针成因
3.1.1. 指针未初始化
#include <stdio.h> int main() { int *p;//局部变量指针未初始化,默认为随机值 *p = 20; return 0; }
3.1.2. 指针越界访问
#include <stdio.h> int main() { int arr[10] = {0}; int *p = arr; int i = 0; for(i=0; i<=11; i++) { //当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i; } return 0; }
3.1.3. 指针指向的空间释放
动态开辟一块空间时返回的值存放到一个指针中,当使用完这个指针后没有释放时,该指针就会变为野指针。
3.2 如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
#include <stdio.h> int main() { int *p = NULL; int a = 10; p = &a; //检查指针的有效性 if(p != NULL) { *p = 20; } return 0; }