提供网站制作公司电话,网站如何引入流量,百度网站地图怎么做,做网站参考文献文章目录 一#xff0c;什么是指针1#xff0c;内存2#xff0c;指针是什么#xff1f; 二#xff0c;指针的声明1#xff0c;声明指针类型变量2#xff0c;二级指针 三#xff0c;指针的计算1#xff0c;两个指针运算符1.1 *运算符1.2 运算符1.3 运算符与… 文章目录 一什么是指针1内存2指针是什么 二指针的声明1声明指针类型变量2二级指针 三指针的计算1两个指针运算符1.1 *运算符1.2 运算符1.3 运算符与*运算符的关系 2指针变量的初始化2.1 指针变量的大坑2.2 指针变量初始化2.3 指针变量初始化最佳实践 三指针的运算1指针与整数值的加减运算2指针与指针的加法运算3指针与指针的减法4指针与指针的比较运算 指针是 C 语言的重点也是难点这篇文章主要讲解指针是什么以及如何使用。
一什么是指针
1内存
指针与内存是息息相关的在学习指针之前先回忆下内存相关的知识。 内存是程序运行期间存储数据的硬件设备为了方便管理计算机将内存划分为一个个小的单元每个单元的大小是一个字节。
如果把内存比作一栋酒店大楼内存单元就像是一个个小的房间数据就住在小房间里。 我们知道为了客人能准确找到属于自己的房间酒店房间是有房号的。 同样内存单元也是有编号的这个编号在计算机中称之为“内存地址”。 2指针是什么
指针就是内存单元的编号本质上是一个内存地址相当于房卡上的房间号。
从形式上看指针和整型数据并没有什么区别都是数字。区别在于指针是内存地址不用于与其他数据进行加减乘除等运算也不会展示给用户。
二指针的声明
1声明指针类型变量
在编写代码过程中通常会声明一个变量然后对变量进行赋值或者其他各种运算。
要使用指针也需要声明一个指针类型的变量。
一定要牢记指针变量就是一个普通变量只不过它的值是内存地址而已。
指针类型由两部分构成
①指针标识符C语言用字符*表示指针②指针类型指针不能单独存在必须和数据类型一起出现表明这个指针是某种数据类型的指针
比如char*表示一个指向字符的指针float*表示一个指向float类型的值的指针。
int* intPtr;上面示例声明了一个变量intPtr它是一个指针指向的内存地址存放的是一个整数。
星号*可以放在变量名与类型关键字之间的任何地方下面的写法都是正确的。
int *intPtr;
int * intPtr;
int* intPtr;推荐使用星号紧跟在类型关键字后面的写法即int* intPtr;。
声明指针变量时需要注意如果要在一行声明多个指针变量每个变量前都要携带字符*。
// 正确
int * foo, * bar;// 错误
int* foo, bar;上面示例中第二行实际上仅仅声明了一个指针变量foo是整数指针变量而bar是整数变量即*只对第一个变量生效。
2二级指针
一个指针指向的可能还是指针这时就要用两个星号**表示这种指针通常称为二级指针。
int** foo;上面示例表示变量foo是一个指针即变量foo存储的还是一个内存地址这个内存地址指向的内存中存储的则是一个整数。
int a 10;
// a表示a变量的内存地址
int* pa a;
// a表示指针变量pa的内存地址
int** ppa pa;三指针的计算
1两个指针运算符
1.1 *运算符
*这个字符除了声明变量时代表指针外还可以作为运算符用来获取指针指向的内存中的值。
void plus1(int* p) {*p *p 1;
}上面代码中函数plus1的参数是一个整数指针p。
函数体里面*p就表示指针p所指向的那个整数值。
对*p赋值就是改变指针p指向的内存中的值。
这有点绕和普通变量对比更容易理解。
int a 10;
int b 100;
// 将b的地址赋于指针pb
int* pb b;*pb *pb 1;
a a 1;对于上述代码的最后两行
*pb *pb 1这个表达式可以拆解为4步①计算机首先从指针变量pb中取出地址0xffeecc②再去这个地址指向的内存单元中获取整数100③然后执行运算1001执行完成后④0xffeecc这个内存单元的值就变成101。a a 1相当于上面的表达式执行过程更简单。①计算机从变量a对应的内存直接取出整数10②然后执行运算101③执行完成后a变量对应的内存的数据更新为11。
1.2 运算符
运算符用来取出一个变量所在的内存地址。
int x 1;
printf(xs address is %p\n, x);上面示例中x是一个整数变量x就是x的值所在的内存地址。printf()的%p是内存地址的占位符可以打印出内存地址。
上一小节中参数变量加1的函数可以像下面这样使用。
void plus1(int* p) {*p *p 1;
}int x 1;
plus1(x);
printf(%d\n, x); // 2注意调用plus1()函数以后打印变量x的值发现结果是2但是我们并没有对x进行显示的重新赋值原因调用plus1函数时将变量c的地址作为参数进行传递plus1直接根据地址取出初始值执行加1的运算然后更新内存中的值为2不必使用变量x就可以修改x变量的值。
1.3 运算符与*运算符的关系
运算符与*运算符互为逆运算下面的表达式,是成立的。
int i 5;if (i *(i)) // 正确2指针变量的初始化
2.1 指针变量的大坑
声明指针变量之后编译器会为指针变量本身分配一个内存空间这个内存空间可能还保存着历史数据。
也就是说这个指针变量可能指向一个随机的地址。
如果此时就去读写这个地址对应的内存可能出现非常严重的后果必然这个地址指向的是账户余额有可能导致账户虚增或者虚减。
int* p;
*p 1; // 错误上述代码是必须避免的因为指针p指向的内存单元是随机的。
2.2 指针变量初始化
正确写法是声明指针变量声明立即指向一个明确的地址这就是指针变量的初始化初始化之后再进行读写。
int* p;
int i;p i;
*p 13;上面示例中p是指针变量声明这个变量后p会指向一个随机的内存地址。
这时要将它指向一个已经分配好的内存地址上例就是再声明一个整数变量i编译器会为i分配内存地址然后让p指向i的内存地址p i;。
完成初始化之后就可以对p指向的内存地址进行赋值了*p 13;。
2.3 指针变量初始化最佳实践
强烈推荐声明指针变量的同时将指针变量的值设为NULL。
int* p NULL;NULL在 C 语言中是一个常量表示地址为0的内存空间这个地址是无法使用的读写该地址会报错。
这样即使之后我们忘记了把指针变量p指向预期的内存地址在程序运行过程中会报错而不是以可怕的、随机的方式运行。
三指针的运算
我们现在知道了指针虽然代表的是内存地址但其本质上是一个无符号整数。
C语言允许指针参与运算但是指针的运算规则和整数的运算规则是相差很大的。
1指针与整数值的加减运算
指针与整数值的运算表示指针的移动。
short* j;
j (short*)0x1234;
j j 1; // 0x1236上面示例中j是一个指针指向内存地址0x1234。
由于0x1234本身是整数类型int跟j的类型short*并不兼容所以强制使用类型投射将0x1234转成short*。
表明上看j 1应该等于0x1235但正确答案是0x1236。
原因是j 1表示指针向内存地址的高位移动一个单位而一个单位的short类型占据两个字节的宽度所以相当于向高位移动两个字节。同样的j - 1得到的结果是0x1232。
指针移动的单位与指针指向的数据类型有关。数据类型占据多少个字节每单位就移动多少个字节。
2指针与指针的加法运算
指针只能与整数值进行加减运算两个指针进行加法是非法的。
unsigned short* j;
unsigned short* k;
x j k; // 非法上面示例是两个指针相加这是非法的。
3指针与指针的减法
相同类型的指针允许进行减法运算返回它们之间的距离即相隔多少个数据单位。
高位地址减去低位地址返回的是正值低位地址减去高位地址返回的是负值。
这时减法返回的值属于ptrdiff_t类型这是一个带符号的整数类型别名具体类型根据系统不同而不同。这个类型的原型定义在头文件stddef.h里面。
short* j1;
short* j2;j1 (short*)0x1234;
j2 (short*)0x1236;ptrdiff_t dist j2 - j1;
printf(%td\n, dist); // 1上面示例中j1和j2是两个指向 short 类型的指针变量dist是它们之间的距离类型为ptrdiff_t值为1因为相差2个字节正好存放一个 short 类型的值。
4指针与指针的比较运算
指针之间的比较运算比较的是各自的内存地址哪一个更大返回值是整数1true或0false。