前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >指针的深入解读笔记

指针的深入解读笔记

作者头像
发布2024-04-30 21:14:22
760
发布2024-04-30 21:14:22
举报
文章被收录于专栏:转自CSDN转自CSDN

指针是什么

指针是指向内存单元的编号(地址),可以快速访问地址,加快程序运行速度.

在指针中一般用到两个操作符:

* 解引用操作符 也是定义指针时候的操作符

int *p;//定义一个类型为 int 的 指针 *p = 0;解引用p指向的地址 并且赋值为0

& 取地址操作符

int a; int *p; p = &a;//把a的地址给p

int * p 中 *说明p是指针变量 int 说明 p 指向的类型是整型

而且p中存储的是地址 *p是解引用p指向了 变量 也就是 p(地址) --> a(变量)

指针本身也占有大小,而且在32位平台下是4字节 64位平台下是8字节 而且指针大小与它所指向的东西无关,只于它运行的平台有关

指针类型意义

指针变量的类型虽然与大小无关,但是却决定每次或下次访问时访问的字节大小有关

比如char*类型的指针,每次只访问一个字节

int*类型的指针,每次访问四个字节

而且它也决定 与 + - 运算时访问字节的大小 也就是指针的类型决定了指针向前或者向后走一步有多大距离.

比如char*类型的指针每次 +1 跳过1个字节

int*类型的指针每次 +1 跳过四个字节

而且指针的地址是可以求差的,用差除去每个元素的长度可以得到两个地址之间的元素个数

而且还有一种特殊指针 void* 它是无具体类型的指针(泛型指针),这种指针可以接收任何类型的地址,但是不可以与 + - 和 解引用 因为它无法确定 步长.

一般情况下void*指针是使用在函数参数的部分,用于接收不同类型的地址,可以实现泛型编程的效果,例如

qsort使用-CSDN博客 中 qsort模拟部分

而且指针使用可以和 const(不可修改) 来修饰 而且 const的位置决定可改变和不可改变的位置

const int * p;//决定的是*p不能改变 int const *p;//同理

int * const p;//决定的是p指向的地址不可更改,但是地址包含的东西可以更改

野指针是指向未知位置的指针,一般是由于没有初始化,越界访问,指向了已经被释放的空间等.我们要规避野指针的存在,可以初始化的时候赋值NULL(空地址0) ,在使用完不使用指针的时候及时赋NULL,避免返回局部变量的地址等方法.

也可以使用assert断言 也就是assert.h的头文件包含的assert(),用于在运行时确保程序符合指定条件,如果不符合就报错并且终止运行程序

assert(p != NULL);//如果p不是空指针就报错

如果assert接收的返回值是0就回报错,不是0就继续运行,而且要关闭断言可以使用

#define NDEBUG

数组名指针

首先举个小例子

int arr[5] = {1,2,3,4,5}; int *pp = &arr[1];//取到了元素2的首地址 每次 + 1 会跳过一个元素 int *ppp = arr;//取到了数组第一个元素的首地址 每次 + 1会跳过一个元素 int *pppp = &arr;//取到了整个数组首元素地址 每次+1会跳过一个数组

我们根据例子也可以倒推如何使用指针去找元素,就和+1 -1和取得是什么类型的指针有关

printf("%d",arr[1]); printf("%d",*pp); printf("%d",pp[0]); printf("%d",*(pp+0);

这四个代码的效果是一样的 其实[]可以和*一样有解引用的功能

在本质上pp[i]和*(p+i)是等价的 同理arr[i]和*(arr+i)也是等价的

数组元素的访问在编译器处理的时候,也是转换成首元素的地址 + 偏移量 然后求出元素的地址,然后再解引用访问.

一维数组的本质

本质上素组窜惨本质上传递的是首元素(或者选择的元素)的地址,因为传过去的仅仅只是地址,所以在自定义函数里面无法直接用sizeof求出数组的大小,只能求出这个地址的大小.而且可以用指针的形式接收数组,因为是地址.

二级指针

指针变量也是变量,所以指针本身也有地址,而且这个地址也可以由其它指针接收,也就是二级指针.

int a; int *p = a; int * *pp = a;

在这种情况下 pp解引用调用p的内容(a的地址) 再对pp二次解引用才能找到a pp中存放的是p的地址 p中存放的是a的地址.

指针数组(与数组指针区分一下)

对于普通的数组 它存放的是int类型的内容

int a[5] == { int,int.......}

对于指针数组 他存放的是是int*类型的内容 也就是存放的全是地址 而且每个地址由可以单独指向一个区域

int* a[5] == { int*,int*,....}

指针数组模拟二维数组

以下两个东西是等价的

int arr[3][3];

int arr1 [3]; int arr2 [3]; int arr3 [3]; int* arr[3] = {arr1,arr2,arr3}

其中的arr的效果是相同的,而且根据 arr[i]和*(arr+i)是等价的 可以用相同的方式访问某个元素

也就是 arr[1][1] 等于 *(arr[1] + 1) 等于 *(*(arr + 1) + 1)

字符指针变量

再指针的类型中 还有 char* 的类型 ,它每次访问一个字节,可以逐字节访问

char a = 'w'; char *p = a;//那么p指向a的地址 解引用就是字符w

const char * pw ="wwww";//这个pw指向的是在内存中的字符串"wwww"的首地址 const char * pa ="wwww";//这个pa指向的首地址和pw相同

数组指针变量

int *pa[10];这个是指针数组 int (*pb)[10]; 这个是数组指针

int (*pb)[10] pa与*结合说明p是一个指针变量变量,然后指向的是一个大小为10个的整型的素组,p是指针,指向数组,所以是数组指针,( []的优先级高于*,所以要用()保证*先于P结合.

int arr[10] = {0}; int (*p)[10] = &arr;//这里的p就是arr的地址了

&arr 和 p的类型都是 int[10]*

其中 int是p指向的数组的元素类型, p是数组指针的变量名 [10]是p指向数组的元素个数

二维数组的传参本质

首先理解二维数组,二维数组可以看作是每个元素是一维数组的数组,这个数组中的每个元素都是一个一维数组,那么二维数组的首元素就是一个一维数组,取二维数组的数组名时,二维数组的数组名就是第一行的地址,取出来是一个一维数组.

第一行的地址类型是 int(*)[i],那就意味着二维数组传参本质上是传递了地址,传递的是第一行这个以为新数组的地址,那么形参也可以写成指针形式

void test(int (*p)[5]);//用这个来接收有五行的二维数组arr[5][i]

函数指针变量

在内存中创建的自定义函数本身也是有地址的,可以通过 &函数名 的方式得到函数的地址,如果我们要把函数的地址存起来,就要创建函数指针变量,函数指针变量的写法和数组指针类似

void test() { return 0; } void (*pf1)() = &text; void (*pf2)() = test; int add(int x,int y) { return x + y; } int(*pf3)(int,int) = add; int(*pf4)(int x, int y) = &add;

对于 int(*pf3)(int,int) = add; 解析 int 是pf3指向的函数的返回类型 (*pf3)是函数指针变量名

(int,int)是主席昂的函数的阐述类型和个数

这个指针的类型是 int(*)(int,int)

而且用的方法和之间用函数一样的

a = (*pf3)(1,1); a = pf3(1,1);

这两行结果相同

typedef关键字

typedef是重命名例如把 unsigned int 重命名成 unit

typedef unsigned int uint;

函数指针数组

int (*p[5])(int,int);

这是定义了一个 有五个元素,返回类型是int 参数是两个int 的 函数指针数组

类型是 int(*)(int,int)

这个结合到使用的时候也就是转移表了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 指针是什么
  • 指针类型意义
  • 数组名指针
  • 一维数组的本质
  • 二级指针
  • 指针数组(与数组指针区分一下)
  • 指针数组模拟二维数组
  • 字符指针变量
  • 数组指针变量
  • 二维数组的传参本质
  • 函数指针变量
  • typedef关键字
  • 函数指针数组
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档