阜阳网站制作公司报价,什么网站可以发布广告,做网站项目后台的,开发游戏的公司目录
前言
#xff08;一#xff09;内存与地址
从实际生活出发
地址 内存 内存与地址关系密切
#xff08;二#xff09;指针变量
指针变量与取地址操作符
指针变量与解引用操作符
指针的大小
指针的运算
指针 - 整数 指针-指针 指针的关系运算
指针的类型的…目录
前言
一内存与地址
从实际生活出发
地址 内存 内存与地址关系密切
二指针变量
指针变量与取地址操作符
指针变量与解引用操作符
指针的大小
指针的运算
指针 - 整数 指针-指针 指针的关系运算
指针的类型的意义 void* 指针 const修饰指针
野指针
野指针成因 如何规避野指针 前言 C语言是一种直接操作内存的编程语言我们可以直接访问和操作计算机内存中的地址空间。 而C语言中存在的指针类型指针指向的就是内存中的地址。我们可以通过指针来访问和修改内存中存储的数据。 因此深入理解指针并且理解内存对于编写高质量的程序和调试程序故障都非常有帮助。 在理解指针之前我们先引入内存与地址的概念
一内存与地址
从实际生活出发
地址 从实际生活中的问题出发——假如你要去上课但是学校里教学楼那么多如果想要上课就得挨个教室去找这样当你找到上课的教室估计也下课了。 在实际生活中我们是如何解决找东西效率低这一问题呢 ——我们可以将东西排好序提前熟悉它们的位置甚至编好号。 我们将每栋教学楼的每一个房间一一编号这样你要去上课只要有了楼号和房间号就可以快速找到房间找到教室。
于是C语言借鉴生活中的实例从而有了地址的概念。 内存 我们知道计算上CPU中央处理器在处理数据的时候需要的数据是在内存中读取的处理后的数 据也会放回内存中。 我们买电脑的时候电脑上内存是8GB/16GB/32GB等那这些内存空间如何高效的管理呢 其实也是把内存划分为⼀个个的内存单元每个内存单元的⼤⼩取1个字节。 一个字节有多大呢 常见内存单位 1byte字节 8bit 1KB 1024byte 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB 一个内存单元的大小取为1字节是比较合适的如果取得过大那么计算机的内存就会小很多如果过大那么内存无法被高效利用 内存与地址关系密切 每个内存单元也都有⼀个编号这个编号就相当于教学楼的门牌号有了这个内存单元的编号CPU就可以快速找到⼀个内存空间。 生活中我们把门牌号也叫地址在计算机中我们 把内存单元的编号也称为地址。 C语⾔中给地址起了新的名字————指针
所以我们可以理解为 内存单元的编号 地址 指针 二指针变量
指针变量与取地址操作符 我们对内存和地址有了初步的了解我们再回到C语言在C语言中创建变量其实就是向内存申请空间
#include stdio.h
int main()
{int a 10;return 0;
} ⽐如上述的代码就是创建了整型变量a内存中申请4个字节用于存放整数10其中每个字节都有地址上图中4个字节的地址分别是
0x007DF784 0x007DF785 0x007DF786 0x007DF787 上图中出现了一个陌生的操作符—— 取地址操作符 作用取出变量的地址 比如我们可以将a的地址放在pa中并用%p 打印出来 但是我们发现打印出的只有一个地址 并且与第一次看到的a的地址不同
原因在于 1.每一次运行代码编译器都会重新给变量分配内存空间这也就解释了为什么第二次打印的地址与第一次不同。 2.同时虽然整型变量占用4个字节我们只要知道了第⼀个字节地址顺藤摸瓜访问到4个字节的数据也是可行的。 在上图中又出现了一个陌生的操作符
指针变量与解引用操作符 我们通过取地址操作符()拿到的地址是⼀个数值如0x006FFD70这个数值有时候也是需要 存储起来⽅便后期再使用的那我们把这样的地址值存放在哪里呢 答案是指针变量中。 我们可以通过创建一个指针变量来存储变量的地址
#includestdio.h
int main()
{int a 100;int* pa a;*pa 0;
} *pa 的意思就是通过pa中存放的地址找到指向的空间 *pa其实就是a. 于是解引用操作符的作用就是通过地址找到对应的变量。 指针的大小 我们知道32位机器假设有32根地址总线每根地址线出来的电信号转换成数字信号后 是1或者0那我们把32根地址线产⽣的2进制序列当做⼀个地址那么⼀个地址就是32个bit位需要4 个字节才能存储。 如果是32位机器那么指针的大小是4个字节。 如果是64位机器指针的大小是8个字节。
int main()
{printf(%zd\n, sizeof(char *));printf(%zd\n, sizeof(short *));printf(%zd\n, sizeof(int *));printf(%zd\n, sizeof(double *));return 0;
}如图演示 注意指针变量的大小和类型是无关的只要指针类型的变量在相同的平台下大小都是相同的。 既然指针的大小与类型无关那么指针类型存在的意义是什么
在讨论这个问题之前我们先引入指针的运算
指针的运算 指针的基本运算有三种分别是
• 指针- 整数
• 指针-指针
• 指针的关系运算 指针 - 整数
#include stdio.h
//指针- 整数
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,10};int *p arr[0];int i 0;int sz sizeof(arr)/sizeof(arr[0]);for(i0; isz; i){printf(%d , *(pi));//pi 这⾥就是指针整数}return 0;
} 1.数组在内存中是连续存放的只要知道第⼀个元素的地址顺藤摸瓜就能找到后面的所有元素。 2.指针加减整数表示跳过当前指针类型的元素的个数。 指针-指针
//指针-指针
#include stdio.h
int my_strlen(char *s)
{char *p s;while(*p ! \0 )p;return p-s;
}
int main()
{printf(%d\n, my_strlen(abc));return 0;
} 1.图中实现的是strlen函数的模拟实现 2.指针-指针 表示两个指针变量之间的元素的个数 指针的关系运算 //指针的关系运算
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,10};int *p arr[0];int i 0;int sz sizeof(arr)/sizeof(arr[0]);while(parrsz) //指针的⼤⼩⽐较{printf(%d , *p);p;}return 0;
}1.指针的关系的比较实际上就是地址大小的比较。 指针的类型的意义 1.指针的类型决定了对指针解引用的时候有多大的权限⼀次能操作几个字节。 //代码2
#include stdio.h
int main()
{int n 0x11223344;char* pc (char*)n;*pc 0;return 0; 对于n的地址 *pc 0之前 之后 2.指针的类型决定了指针向前或者向后一步有多大距离。
#include stdio.h
int main()
{int n 10;char *pc (char*)n;int *pi n;printf(%p\n, n);printf(%p\n, pc);printf(%p\n, pc1);printf(%p\n, pi);printf(%p\n, pi1);return 0;
}我们可以看出 char* 类型的指针变量1跳过1个字节 int* 类型的指针变量1跳过了4个字节。 这就是指针变量的类型差异带来的变化。 void* 指针 在指针类型中有⼀种特殊的类型是 void* 类型的可以理解为无具体类型的指针或者叫泛型指 针这种类型的指针可以用来接受任意类型地址。但是也有局限性 void* 类型的指针不能直接进行指针的-整数和解引用的运算。 const修饰指针
见详解
const修饰指针https://mp.csdn.net/mp_blog/creation/editor/134341320
野指针 概念 野指针就是指针指向的位置是不可知的随机的、不正确的、没有明确限制的
野指针成因 1. 指针未初始化 2. 指针越界访问 3. 指针指向的空间释放 3的实例 #include stdio.h
int* test()
{int n 100;return n;
}
int main()
{int*p test();printf(%d\n, *p);return 0;
}如何规避野指针 1.指针初始 2.小心指针越界 3.指针变量不再使用时及时置NULL指针使用之前检查有效性 4.避免返回局部变量的地址 5.assert断言 完~
未经作者同意禁止转载