目录
下面这一张图,我们可以看到a初始化为20 ,int* p指向a的地址
指针变量和地址
取地址操作符
&取地址操作符可以取出一个变量的地址
下面在32位环境下打印地址,我们可以看到取出a的地址打印
下面这张图,我们在编译过程中,我们也可以查看内存
指针变量的大小
在32位环境下有32根地址总线4X8=32
32位平台下地址是32个bit位,指针变量⼤⼩是4个字节?
在64位环境下有64根地址总线8X8=64
64位平台下地址是64个bit位,指针变量⼤⼩是8个字节
指针变量类型意义
指针解引⽤
int a=20;
int *p = &a;//p指向a的地址
*p = 99;//通过解引⽤把地址变成20,然后进行修改
上面这*p指向的是a的地址,然后再通过解引⽤把地址变成20,然后进行修改成99
下面这代码p如果不解引⽤那么p就是修改int *p指向的地址
int a = 10;
int b = 20;
int *p = &a;//p指向a的地址
p = &b;//这个是修改p指向的地址
//上面修改了p指向的地址,那下面这个修改的就是 b 的数值了
*p = 0;
下面我们可以看到地址是倒着存放的,int是4个字节,11,22,33,44刚刚好4个
每次编译或执行编译器都会重新分配内存空间
当我们执行*p = 0的时候,我们可以发现全部变成0了,因为int *是4个字节。
下面是char *我们可以发现只改了一个地址,因为char *是一个字节
指针的 + - 整数
下面这代码,我们可以看到int *p是int类型的也就是4个字节
p+1我们可以看到往后跳了4个
char * cp是char类型的也就是1个字节
cp+1我们可以看到往后跳了1个
往后跳多少取决于类型是多少,如果类型是8个字节那么就往后跳8个
const修饰指针
const修饰变量
我们可以发现被const修饰变量不能被修改,拥有了常属性
a拥有了常属性,但是不能当常量使用,会报错
我们可以发现被const修饰的变量,用指针的方式通过地址解引⽤后进行修改
举个例子一个房间里大门被const修饰进不去了,可以通过指针也就是翻窗户进去
我们可以发现const也把指针修饰了,也就是说把窗户也关起来了,谁都进不去了
const修饰指针变量
const修饰指针,const在 * 号前面那么数值就不能修改了
const在*号后面的话,地址不能被修改了
指针的运算
指针+ -整数
下面,我们可以发现int *p指向数组首元素地址,for循环通过数组首元素地址加1一直访问到最后一个元素
指针-指针
我们可以看到char* x指向p的首元素地址
然后while循环,每次循环加1,加1跳过类型大小,访问到下一个地址
加到‘\0’停止,每个字符串后面都会有'\0','\0'也是字符串的结束标志
p加到\0停止到了最后一个元素,然后通过最后一个元素的地址减去首元素地址,就可以拿到总共有多少个元素了
指针的关系运算
野指针
野指针就像一只疯狗,不把狗栓在树上很危险
指针未初始化
指针未初始化那么指针默认就是随机值
指针越界访问
数组只有10个元素,用指针越界访问到第12个元素,就会成野指针了
指针指向的空间被释放了
下面这个可以运行,但是也是个野指针,很危险
这个函数,返回了n的地址后,这个函数的空间就被释放了,p指向了一个被释放的空间,就是野指针了
避免野指针
当指针没有地址初始化,我们只需要给个NULL就可以避免野指针了
assert断言
使用assert函数我们需要下面这个头文件
#include <assert.h >
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报
错终⽌运⾏。这个宏常常被称为“断⾔”
用assert可以判断p是不是NULL是NULL就报错并且显示在第几行
p不为空就往下执行
assert() 的使⽤对程序员是⾮常友好的,使⽤ assert() 有⼏个好处:它不仅能⾃动标识⽂件和
出问题的⾏号,还有⼀种⽆需更改代码就能开启或关闭 assert() 的机制。如果已经确认程序没有问
题,不需要再做断⾔,就在 #include <assert.h> 语句的前⾯,定义⼀个宏 NDEBUG 。
如果是我们想让assert全部失效我们可以添加下面这个头文件
#define NDEBUG
然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。如果程序⼜出现问题,可以移
除这条 #define NDBUG 指令(或者把它注释掉),再次编译,这样就重新启⽤了 assert() 语
句。
我们可以看到p是NULL,加上这个头文件,assert失效了,如果有多个assert那么全部失效
当然我们在Release环境下执行会自动过滤assert
传值调⽤和传址调⽤
传值调用
传值调用就是传数值到函数里
下面这代码,在函数里交换后就释放了,
传址调用
传值调用就是传地址解引⽤进行交换,通过地址进行的交换,空间释放了,不会影响地址
标签:const,变量,int,C语言,assert,地址,指针 From: https://blog.csdn.net/2401_86723175/article/details/141126972