指针小笔记

一级指针

在我们创建变量时,内存会开辟出一个空间来存放这些变量,内存会被划分为一个个内存单元,每个内存单元的大小是一个字节,而每个内存单元都会给一个编号
也就是我们的一级指针(平时为了方便就叫做地址)
(注:%p是专门用来打印地址的)

指针变量

为了存放这些地址我们就需要创建一个专门的变量来存放地址,也就是指针变量
例如:

int a=20;
int* pa =&a;

此时pa就是指针变量,里面存放的就是a的地址在int * pa中 * 说明pa是一个指针
而int是pa这个指针指向的类型.
对于数组来说数组名就是数组首元素的地址,但有两个例外
1 sizeof(数组名), 这里的数组名表示整个数组,计算的是整个数组的大小
2 &数组名, 这里的数组名也表示整个数组,取出的是整个数组的地址

指针变量需要多大空间,取决于存放的是什么 当存放的是地址时
地址的存放需要多大空间,指针变量的大小就是多大
32位机器上存储需要32个bit位,也就是4个字节,指针变量大小就是4个字节
64位机器上存储需要64个bit位,也就是8个字节,指针变量大小就是8个字节

解引用操作符

*就是我们的解引用操作符

printf"%d\n",*pa);

*pa就是解引用操作 *pa==a

指针类型

指针类型决定了指针进行解引用操作时访问多大空间
例如:
int* 的指针解引用访问到4个字节
char* 的指针解引用访问到1个字节

  • 指针类型决定了指针的步长,就是向前/向后走一步走多大距离
    根据规律我们可以得出
    type* p
    p+i 是跳过i个type类型的数据
    相当于跳过了i*sizeof(type)个字节

const修饰指针

添加了const就说明这是常属性–不能被修改
(当然不等于将被定义的变量转化成了常量,其本质是一个不可改变的常变量)
当const修饰指针时分为两种情况

  • 放 * 左边 int const * p=&n; 修饰/限制的是*p不能通过p来改变p指向的对象 但p可以指向其他对象
  • 放 * 右边 int * const p=&n; 修饰/限制的是p不能改变p本身的值 ‘’ 但p指向的内容可以通过p来改变

指针的运算关系

前提:要两个指针指向同一块空间
指针-指针的绝对值 得到的是指针和指针之间的元素个数
数组的地址+1 跳过的是整个数组
数组的首元素+1 跳过的是4个字节
arr[i]== * (arr+i)==*(p+i)==p[i]

野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。例如:未初化,越界,空间释放
都会应发野指针

预防野指针

  • 指针初始化
    int* p=NULL;
    NULL是一个标识符常量 内容是0 地址也是0(不可读写/使用)
    *使用指针前要看是不是空指针(首先要初始化)
  • 小心指针越界
    指针不再使用后,及时置NULL,使用前检查有效性
    避免返回局部变量的地址

assert断言

assert.h头文件定义了宏 assert()由于在运行时确保程序符合条件,如果不符合,就报错终止程序,以此来达到防止野指针的情况

assert(p !=NULL)

若表达式为0,则会报错
如果已经不需要assert再进行断言,则在assert.h头文件前加上#define NDEBUG
这样就不会再运行assert()减少运行时间

  • release版本里会选择性优化掉assert

指针数组

存放指针的数组

int arr1[]={1,2,3,4,5};
int arr2[]={2,3,4,5,6};
int arr3[]={3,4,5,6,7};

int* arr[3]={arr1,arr2,arr3};//指针数组

字符指针变量

const char* p=“hello world”//指向的是首字符的地址 常量字符串相同内容只会创建一份
(不允许修改)

数组指针变量—存放数组地址的指针变量

int arr[10]={0};
int (*p)[10]=&arr;//p是数组指针 (p)说明p是个指针 [10]说明指向的是数组 int说明是整型
int (
)[10]是p的数组指针类型
p指向的是数组,数组10个元素,每个类型是int
数组指针通常会在二维数组中使用

在二维数组中,数组名就是第一行的地址
第一行是一个一维数组

函数指针变量—指向函数 存放函数的地址

&函数名 得到函数的地址
&函数名和函数名都表示函数的地址
函数返回类型 (*pf)(形参类型,形参类型)=&函数名 //pf是函数指针变量
(*pf)(实参,实参)或 pf (实参,实参)

typedef关键字 是用来类型重命名

typedef unsigned int uint 将unsigned int简化为uint
typedef int* uint
对于数组指针类型的简化时要将修改后的名称放在右边
对于函数指针类型同理
typedef int(
parr_t)[5]
parr_t等价于int(*)[5]

函数指针数组—存放函数指针的数组

如果要把多个函数类型相同的函数指针存放到同一数组,就是函数指针数组

int (*pfarr[4])(int,int) pfarr就是函数指针数组
调用: pfarr[i]( 实参, 实参)

qsort --用来排序

qsort是库函数 可以直接用来排列数据
头文件是stdlib
qsort(等待排序数组的第一个元素,等待排序数组元素个数,等待排序数组的元素大小,指向两个元素的比较函数)

int cmp_int(const void* p1,const void* p2)//整型比较函数  升序
{
return *(int*)p1-*(int*)p2;//void*不能直接读写所以要转换成整型指针
//>0  返回  >0的数
//<0   返回   <0的数
//==0   返回  0
}

sizeof与strlen

sizeof只在乎内存空间所占大小,不在乎内容
strlen 是个库函数头文件是string.h 求字符串长度(只针对字符串)不遇到\0
就不会停止

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值