尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

指针详细总结

指针详细总结 目录一.指针是什么二.指针和指针类型2.1指针类型的声明和变量的取地址2.2指针的解引用2.3指针类型2.4 NULL指针2.5指针的大小三.野指针3.1野指针的定义3.2野指针的危害3.3野指针成因1.指针未初始化2. 指针越界访问3.指针指向的空间释放4.在超越变量作用域下使用指针3.4如何规避野指针四.指针的三种运算4.1 指针 - 整数4.2指针减指针4.3指针的关系运算五.指针数组和数组指针5.1指针数组5.2数组指针5.3指针数组和数组指针的区别六.二级指针一.指针是什么理解指针的两个要点1.我们知道计算机上CPU中央处理器在处理数据的时候需要的数据是在内存中读取的处理后的数据也会放回内存中。为了高效管理内存空间我们会把内存划分成一个一个的内存单元每个内存单元的大小为1字节每个内存单元都有一个编号。指针就是内存中最小单元的编号也就是地址。2.平时所说的指针通常指的是指针变量是用来存储地址的变量类型。总的来说指针就是地址口语中的指针通常指指针变量其值是另一个变量的地址也就是内存的单元编号。如图所示如上图所示一个格子是内存最小单元格子右边的数字是16进制形式的地址编号即指针。二.指针和指针类型2.1指针类型的声明和变量的取地址我们可以用类型名 *来声明指针变量使用取地址操作符取变量地址赋给指针变量示例#includestdio.h int main() { int a 0; int* pa a; printf(%p,pa); return 0; }如上pa中储存的就是储存整型变量a所用的地址编号 .运行结果如下所示此时的编号就是变量a在内存中的位置。注*p a 是错误的 int* p a、p a正确。2.2指针的解引用我们可以用解引用操作符*来解引用指针通过指针访问对应的数据。示例#includestdio.h int main() { int a 10; int* pa a; printf(%d, *pa); return 0; }运行结果如下通过解引用整型指针pa来访问变量 a 中存储的数据。我们也可以通过解引用指针来修改变量的数据。示例#includestdio.h int main() { int a 10; int* pa a; *pa 20; printf(%d, *pa); return 0; }运行结果如下2.3指针类型指针类型是C语言中数据类型之一与数组整型int字符型插入等类型同级别。指针类型可以是整型指针int*单精度浮点型指针float*双精度浮点型指针double*甚至是函数指针自定义数据类型指针等。指针所指向的类型决定了编译器将指针所指向的内存区域里的内容当成什么来看待。示例#includestdio.h int main() { int a; int*pa a; printf(%p\n, pa); printf(%p\n, pa 1); printf(%p\n, (float*)pa 1); printf(%p\n, (double*)pa 1); printf(%p\n, (long long*)pa 1); return 0; }运行结果如下图所示由此可知整型变量a的存储地址是00S3FD98变量a的地址加一是00D3FD9C切换成单精度浮点型地址后加一也是00D3FD9C两种类型的指针变量增加的量刚好是数据类型所占有的空间大小——4字节而切换成双精度浮点类型指针后增加的量是其对应的空间大小——8字节。指针的增加量就是我们常说的指针的步长。总的来说指针类型决定这编译器对该地址或该地址的数据的类型而有着不同的计算方式。指针类型的作用还包括解引用时访问空间的权限有多大。2.4 NULL指针NULL指针就是我们口语中的空指针程序不允许访问地址为0的内存因为该内存是操作系统保留的。常规情况下内存地址0有特殊的意义它表明该指针不指向一个可访问的内存位置如果指针包含空值零值则假定它不指向任何东西。2.5指针的大小我们首先要知道一些基础的知识一个单元有多大1个字节地址是如何编制的对于三十二位机器有三十二根地址线每根地址线有高低电平两种信号高电压低电压用1来表示高电平用0来表示低电平。那么三十二位机器的地址编号也就是指针就可以用四个字节储存一共有二的三十二次方减一种不同的编号。示例#includestdio.h int main() { printf(%d\n, sizeof(int*)); printf(%d\n, sizeof(float*)); printf(%d\n, sizeof(short*)); printf(%d\n, sizeof(char*)); return 0; }我们求出个类型指针所占内存的大小并通过printf函数打印出来结果如下图我们可以知道各类型的指针所占用的内存空间大小相同。当我们使用64位机器时地址线拥有64条就表示者地址编号更多所需要的内存空间就更大。结果如图所示三.野指针3.1野指针的定义概念指针指向的位置是不可知的即指针变量存储的值是随机的不确定的。3.2野指针的危害野指针指向的位置是随机的 危害也是随机的不一定会产生错误。当程序产生错误一般为内存泄露导致程序中断。若野指针指向的位置存放的是一个病毒等东西对其解引用后就会导致电脑中毒。3.3野指针成因1.指针未初始化示例#includestdio.h int main() { int* pa; *pa 20; return 0; }这里我们声明了一个整型指针变量pa但是指针变量未经过初始化则指针变量的值是随机的指向的位置也是随机的即该指针是一个野指针。2. 指针越界访问示例#includestdio.h int main() { int a[] { 1,2,3,4,5 }; for (int i 0; i 5; i) { *(a i) 0; } return 0; }这里通过指针a来访问内存但是访问的不是数组a所使用的内存此时的(a i)就是野指针这里发生的错误就是所谓的越界访问。3.指针指向的空间释放示例#includestdio.h #includestdlib.h int main() { int* a (int*)malloc(sizeof(int)); free(a); *a 10; return 0; }这里我们将申请的空间a释放掉后a指针所指向的空间归还操作系统这时候a就变成了野指针再去解引用整型指针a就可能会发生难以预料的情况。4.在超越变量作用域下使用指针示例#includestdio.h #includestdlib.h int* fun() { int a 10; int* pa a; return pa; } int main() { int* b fun(); return 0; }很明显函数fun中申请的变量生命周期在函数内部出函数后变量销毁此时的b便是野指针。3.4如何规避野指针1.指针初始化。注当指针无值可以赋时我们将其赋值为NULL避免指针是随机变量。2.注意指针越界访问。3.指针指向空间释放后即使赋为NULL避免形成野指针。4.避免返回局部变量地址。5.指针使用之前检查其有效性。四.指针的三种运算4.1 指针 - 整数示例#includestdio.h int main() { int a; int* pa a; double b; double* pb b; char c; char* pc c; printf(%p\n, pa); printf(%p\n, pa 1); printf(%p\n, pb); printf(%p\n, pb 1); printf(%p\n, pc); printf(%p\n, pc 1); return 0; }运行结果如图所示我们可以知道无论指针类型时char、int或者是double其类型指针加一得到的结果时其指向的地址加上数据类型所占内存的大小字节。指针减整数同理示例#includestdio.h int main() { int a; int* pa a; double b; double* pb b; char c; char* pc c; printf(%p\n, pa); printf(%p\n, pa - 1); printf(%p\n, pb); printf(%p\n, pb - 1); printf(%p\n, pc); printf(%p\n, pc - 1); return 0; }运行结果如下4.2指针减指针1指针和指针可以做减法操作但不适合做加法运算。2两个指针都指向同一个数组。3相减结果为两个指针之间的元素数目而不是两个指针之间相差的字节数。示例#includestdio.h int main() { int a[] { 1,2,3,4,5,6 }; printf(%d\n, a[5] - a); printf(%d\n, a - a[5]); return 0; }运行结果如下我们不知能看出两个指针相减得到的值是两指针之间的元素数目还能看出来相减之后的结果可以为正也可以为负但所得结果的绝对值都是一样的。4.3指针的关系运算1.两指针指向同一个数组。2.通过比较我们可以知道同一数组的两个指针哪个更靠后。3.标准未定义两个任意的指针相比较会发生什么。示例#includestdio.h int main() { int a[] { 1,2,3,4,5 }; if (a a[4]) printf(a a[4], *a, a[4]); return 0; }结果如下所示由此我们可以得到 a[4] 比 a 更加靠后。五.指针数组和数组指针5.1指针数组故名思意就是存放指针的数组。示例#includestdio.h int main() { int a 10; int b 20; int c 30; int* d[3] { a,b,c }; printf(%p\n%p\n%p, *d, d[1], d[2]); return 0; }运行结果如下所示这里数组小标操作符 [] 的优先级高于解引用操作符*d 会先与数组小标操作符相结合再与解引用操作符结合即形成存放三个元素类型为 int* 的首元素地址为d的数组。5.2数组指针顾名思义就是指向数组的指针。示例#includestdio.h int main() { int a[][3] { 1, 2, 3, 4, 5, 6 }; int(*pa)[3] (a[0]); for (int i 0; i 2; i) { printf(%d: %p, %p\n, i, *(a i), pa i); } return 0; }运行结果如下所示易知pa中储存的是含有三个元素的数组的地址。5.3指针数组和数组指针的区别1.数组指针是一个指针指向一个数组指针数组是一个数组里面的元素都是指针。2.指针数组的写法*p[3]数组指针的写法(*p)[3]3数组指针是一个变量占用一个指针存储空间而指针数组是多个变量占用两个或以上的指 针存储空间。六.二级指针二级指针的定义二级指针是指向一级指针的指针。说白了就是指针的指针。示例#includestdio.h int main() { int a 10; int* pa a; int** ppa pa; printf(%p\n, pa); printf(%p\n, ppa); printf(%p\n, *ppa); printf(%d, **ppa); return 0; }运行结果如下所示我们可以看出解引用ppa得到的是a的地址即pa的值而对ppa两次解引用得到a的值ppa中储存的是pa的地址此时的ppa就是所谓的二级指针他指向pa。
返回列表