[C][指针]详细讲解

目录

  • 0.铺垫
  • 1.指针是什么?
  • 2.指针变量
  • 3.指针和指针类型
  • 4.指针类型的意义
  • 5.野指针
    • 1.野指针成因
    • 2.如何规避野指针
    • 6.指针运算
  • 6.指针和数组
  • 7.二级指针(n级指针)
  • 8.指针数组
  • 9.数组指针
  • 10.&数组名VS数组名
    • 11.函数指针
  • 12.函数指针数组
  • 13.回调函数


0.铺垫

  • 在C中,任何变量&都是从最低地址开始

1.指针是什么?

  • 指针是内存中一个最小单元的编号,也就是地址
  • 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
  • 指针就是地址,口语中说的指针通常指的是指针变量

2.指针变量

  • 可以通过&(取地址操作符)取出变量在内存中的起始地址,把地址可以存放到一个变量中,这个变量就是指针变量
    int a = 10; // 在内存中开辟一块空间
    int *p = &a; // 取出a的地址,将a的4个字节的第一个字节的地址存放在p变量中,p就是要给指针变量
    
  • 总结
    • 指针变量,用来存放地址的变量,存放在指针中的值都被当成地址处理
    • 指针是用来存放地址的,地址是唯一标示一块地址空间的
    • 指针的大小在32位平台是4个字节,在64位平台是8个字节

3.指针和指针类型

  • 指针的定义方式: type + *
  • char*类型的指针是为了存放 char 类型变量的地址
  • short*类型的指针是为了存放 short 类型变量的地址
  • int*类型的指针是为了存放 int 类型变量的地址

4.指针类型的意义

  • 指针类型决定了:指针解引用的权限有多大 -> 能操作几个字节
    • 比如:char*解引用就只能访问一个字节,而int*解引用就能访问四个字节
  • 指针类型决定了:指针走一步,能走多远 -> 步长

5.野指针

  • 概念野指针就是指针指向的位置是不可知的 -> 随机的、不正确的、没有明确限制的

1.野指针成因

  • 指针未初始化
    int *p; // 局部变量指针未初始化,默认为随机值
    *p = 20; // error
    
  • 指针越界访问
    int arr[10] = {0};
    int *p = arr;for(int i = 0; i <= 11; i++)
    {*(p++) = i; // 当指针指向的范围超出数组arr的范围时,p就是野指针
    }
    
  • 指针指向的空间释放

2.如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放即使其置为NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性

6.指针运算

  • 指针±整数
    #define N 5float values[N];
    float *vp = &values[0];// 指针+-整数:指针的关系运算
    while(vp < &values[N])
    {*vp++ = 0;
    }
    
  • 指针-指针
    • 指针和指针相减的前提两个指针指向同一块空间
    • 指针相减,代表指针之间所经历的元素的个数
      int MyStrlen(char* s)
      {char* p = s;while(*p != '\0'){p++;}return p - s;
      }
      
  • 指针的关系运算
    for(vp = &values[N]; vp > &values[0];)
    {*--vp = 0;
    }// 获取你想将代码简化成这样
    for(vp = &values[N - 1]; vp >= &values[0]; vp--)
    {*vp = 0;
    }
    
  • 上述第二种代码实际中在绝大部分的编译器上是可以顺利完成任务的,然而还是应该避免这样写,因为标准并不保证它可行
  • 标注规定
    • 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较
    • 但是不允许与指向第一个元素之前的那个内存位置的指针进行比较

6.指针和数组

  • 数组名表示的是数组首元素的地址
    int arr[10] = {1, 2, 3, 4, 5, 6};
    int *p = arr; // p存放的是数组首元素的地址
    
  • 既然可以把数组名当成地址存放到一个指针中,使用指针来访问一个数组就成为可能
  • 例如
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    int *p = arr; // 指针存放数组首元素的地址
    int sz = sizeof(arr) / sizeof(arr[0]);for(int i = 0; i < sz; i++)
    {printf("&arr[%d] = %p  <==> p+%d = %p\n", i, &arr[i], i, p + i);
    }
    
  • (p+i)其实计算的是数组arr下标为i的地址
    int arr[10] = {1, 2, 3, 4, 5, 6};int* p = arr; // 数组名
    printf("%d\n", arr[2]);
    printf("%d\n", p[2]); // p[2] -> *(p + 2)// []是一个操作符,2和arr是两个操作数
    // 类似于 a + b,b + a
    printf("%d\n", 2[arr]);
    printf("%d\n", arr[2]);// arr[2] -> *(arr + 2) -> *(2 + arr) -> 2[arr]
    // arr[2] <-> *(arr + 2) <-> *(p + 2) <-> *(2 + p) <-> *(2 + arr) <-> 2[arr]
    // 2[arr] <-> *(2 + arr)
    

7.二级指针(n级指针)

  • 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
    • 二级指针存放一级指针的地址,解引用出来是一级指针里的内容
      • *ppa == pa
      • *pa == a
  • n级指针同理
    int a = 10;
    int* pa = &a; // pa是指针变量,一级指针// ppa是一个二级指针变量
    int** pa = &pa; // pa也是个变量,&pa取出pa在内存中起始地址
    

8.指针数组

  • **指针数组是指针还是数组?  **
    • 数组,是存放指针的数组
      int* arr[5];
      

9.数组指针

  • 例如int (*p)[10]
    • p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整形的数组
    • 所以p是一个指针,指向一个数组,叫数组指针
    • 注意[]的优先级高于*,所以必须加上()来保证p先和*结合

10.&数组名VS数组名

  • &arrarr,虽然值一样,但是意义不一样
  • &arr表示的是数组的地址,而不是数组首元素的地址,例如:`int arr[10]
    • &arr的类型是:int(*)[10],是一种数组指针类型
    • 数组的地址 + 1,跳过整个数组的大小,所以&arr + 1相遇&arr的差值是40

11.函数指针

  • &函数名 = 函数名

12.函数指针数组

  • 用途:转移表
  • 样例:计算器(Test.c中)

13.回调函数

  • 回调函数:通过函数指针调用的函数
  • 如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数
  • 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
  • 样例:模仿qsort()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NDIS小端口驱动(九)

PCIe设备难免会遇到一些重置设备的请求&#xff0c;例如重置总线的时候&#xff0c;但是由于NIC网卡的多样性&#xff0c;重置设备确实也有许多要注意的地方&#xff0c;另外还有一些包含WDM的NDIS驱动 微型端口驱动程序硬件重置 微型端口驱动程序必须向 NdisMRegisterMinipo…

C++技能进阶指南——多态语法剖析

前言&#xff1a;多态是面向对象的三大特性之一。顾名思义&#xff0c; 多态就是多种状态。 那么是什么的多种状态呢&#xff1f; 这里的可能有很多。比如我们去买火车票&#xff0c; 有普通票&#xff0c; 学生票&#xff1b; 又比如我们去旅游&#xff0c; 有儿童票&#xff…

视觉与数据的和谐:数字孪生技术在UI设计中的艺术

视觉与数据的和谐&#xff1a;数字孪生技术在UI设计中的艺术 引言 在UI设计的世界里&#xff0c;视觉艺术与数据科学似乎相隔甚远&#xff0c;然而随着数字孪生技术的出现&#xff0c;这两者之间的界限变得模糊。数字孪生技术不仅是一种技术革新&#xff0c;更是一种艺术形式…

LabviewCarla仿真平台搭建一:平台设计及仿真视频可视化实现

文章目录 背景一、平台设计二、视频显示模块实现1、视频模块实现框架2、python-camera数据生成3、labview-camera数据可视化 三、效果展示 背景 在使用carla的时候&#xff0c;有平台的话可以提高效率&#xff0c;因此想结合labview和carla设计一个仿真平台-labcar。其实carla…

【DASBOOK】Mark loves cat

文章目录 一、工具下载二、Mark loves cat解题感悟 一、工具下载 克隆dirsearch仓库&#xff1a; git clone https://github.com/maurosoria/dirsearch.git下载 githack工具 git clone https://github.com/lijiejie/GitHack.git二、Mark loves cat 用dirsearch扫描目录&…

talib 安装

这里写自定义目录标题 talib 安装出错 talib 安装出错 https://github.com/cgohlke/talib-build/releases 这里找到轮子 直接装。

DatePicker日期选择框(antd-design组件库)简单使用

1.DatePicker日期选择框 输入或选择日期的控件。 2.何时使用 当用户需要输入一个日期&#xff0c;可以点击标准输入框&#xff0c;弹出日期面板进行选择。 组件代码来自&#xff1a; 日期选择框 DatePicker - Ant Design 3.本地验证前的准备 参考文章【react项目antd组件-demo:…

算法提高之你能回答这些问题吗

算法提高之你能回答这些问题吗 核心思想&#xff1a;线段树 用sum,lmax,rmax,tmax分别存线段长度,最大前缀,最大后缀,最大子段和 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 500010;int n,m;int w[N];s…

简单3步,ERP、OA、CRM等客户端,安全远程访问服务端

如今&#xff0c;企业员工出差远程办公和分支机构的协同工作变得越来越普遍。然而&#xff0c;如何确保在不同地点的员工都能安全、便捷地访问公司内网的C/S&#xff08;Client/Server&#xff09;架构办公系统&#xff0c;是一个亟待解决的问题。 贝锐花生壳内网穿透服务提供…

zdppy_mcrud操作MySQL数据库教程

01 创建数据库连接 .env配置文件 ZDPPY_MCRUD_HOST192.168.234.130 ZDPPY_MCRUD_PORT3306 ZDPPY_MCRUD_USERNAMEroot ZDPPY_MCRUD_PASSWORDzhangdapeng520 ZDPPY_MCRUD_DATABASEzdppy_mcrud_demo连接到MySQL数据库&#xff1a; import env import mcrudenv.load(".env&…

基于JAVA GUI体育馆管理系统的会员功能

Java GUI即Java图形用户界面&#xff0c;是一种使用图形化元素&#xff08;如窗口、按钮、文本框等&#xff09;来构建用户界面的技术。它基于Java的Swing框架&#xff0c;可以用于创建各种复杂的用户界面&#xff0c;包括窗口、对话框、菜单、按钮、文本框、复选框、下拉列表等…

SQL学习小记(一)

SQL学习小记&#xff08;一&#xff09; 1. 存储过程&存储函数1.1. 存储过程1.2. 存储函数 2. DEFINER3. INSERT INTO&#xff08;插入新记录&#xff09;4. REPLACE()…AS…5. SUM()函数6. CASE WHEN7. STR_TO_DATE日期时间处理函数8. SUBSTRING函数9. dateFormat函数10. …

神奇动物在哪里?斯洛文尼亚旅游之野生动物寻踪

不仅拥有优美动人的自然风光&#xff0c;斯洛文尼亚还以其丰富的生物多样性而闻名。得益于国家对大自然开展的保护工作&#xff0c;斯洛文尼亚超过三分之一的国土面积都被规划为保护区&#xff0c;拥有约1.5万种动物和6000种植物&#xff0c;其中不乏众多特有、稀有和濒危动植物…

美国FDA认证是什么,食品FDA注册申请流程

​美国FDA认证是什么&#xff1f; 美国FDA认证&#xff0c;全称为美国食品药品监督管理局&#xff08;Food and Drug Administration&#xff09;的认证&#xff0c;是美国政府为了确保食品、药品、医疗器械等产品的安全性和有效性所设立的重要制度。FDA认证的种类繁多&#x…

【linux】k掉僵尸进程

ps -ef | grep username | grep -v grep | awk {print $2} | xargs kill -9

DT浏览器有一些特点和优势,可能是人们选择使用的原因

DT浏览器有一些特点和优势&#xff0c;可能是人们选择使用的原因&#xff1a; - 好评如潮&#xff1a;DT浏览器在网络上获得了众多用户的好评&#xff0c;口碑良好。 - 使用微软搜索引擎技术&#xff1a;DT浏览器采用了微软的搜索引擎技术&#xff0c;在搜索内容上提供了国内…

Gitlab安装

配置文件&#xff1a; /etc/gitlab/gitlab.rb日志文件&#xff1a; /var/log/gitlab/数据文件&#xff1a; /var/opt/gitlab/静态文件和网页内容&#xff1a; /opt/gitlab/embedded/service/gitlab-rails/public/ # 查看当前状态 git status # 提交本地更改 git commit -m &q…

反编译 Trino Dockerfile

文章目录 反编译 Trino Dockerfile反编译Dockerfile命令反编译后Dockerfile内容获取 Trino 启动脚本卸载 反编译 Trino Dockerfile 反编译Dockerfile命令 alias dfimage"docker run -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/laniksj/dfimage" d…

通过Wirtinger流进行相位恢复:理论与算法

文章目录 1. 简介2. 算法描述2.1 初始化(Initialization)2.2 迭代更新(Iterative Updates)2.3 学习率调整&#xff08;Learning Rate Adjustment&#xff09; 3. 代码实现3.1 一维信号测试 &#xff08;Gaussian model&#xff09;3.2 一维信号测试 &#xff08;Coded diffract…

基于Netty实现WebSocket客户端

本文是基于Netty快速上手WebSocket客户端&#xff0c;不涉及WebSocket的TLS/SSL加密传输。 WebSocket原理参考【WebSocket简介-CSDN博客】&#xff0c;测试用的WebSocket服务端也是用Netty实现的&#xff0c;参考【基于Netty实现WebSocket服务端-CSDN博客】 一、基于Netty快速…