第四节——从深层剖析指针(让你不再害怕指针)

文章目录
- 1. 字符指针变量
- 剑指offer例题
- 2. 数组指针变量
- 2.1 数组指针变量是什么?
- 2.2 数组指针变量怎么初始化
- 3. ⼆维数组传参的本质
- 代码实现
- 4. 函数指针变量
- 4.1 函数指针变量的创建
- 4.3 两段有趣的代码
- 4.3.1 typedef 关键字
- 5. 函数指针数组的定义
1. 字符指针变量
在指针的类型中有一种指针类型叫字符指针char*
简单代码如下:
int main()
{char ch = 'w';char *pc = &ch;*pc = 'w';return 0;
}
再看如下代码:
int main(){const char* pstr = "hello bit.";printf("%s\n", pstr);return 0;}
这里是把⼀个字符串(hello bit.)放到指针变量里了吗?
其实本质是把字符串hello bit 首字符的地址放到了pstr中(pstr指向字符串的首字符的地址)。

剑指offer例题
下面我们一起来欣赏下这道剑指发的题目
#include <stdio.h>int main()
{char str1[] = "hello bit.";char str2[] = "hello bit.";const char *str3 = "hello bit.";const char *str4 = "hello bit.";if(str1 ==str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if(str3 ==str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
a.首先,我们要清楚:创建数组名str1为其开辟了一块空间,str2也等同开辟了一块空间,显然,二者的地址并不相同。
我们又知道,数组名比较的是首元素的地址,因此str1 != str2。
b.字符串“hello bit.”向内存申请了一块空间,指针str3指向了字符串的首元素的地址,str4也是指向字符串首元素的地址。
由于hello bit.的地址并不发生变化,即str3和str4都是指向同一个地址,那么str3 == str4。
2. 数组指针变量
2.1 数组指针变量是什么?
前面我们学习了指针数组,指针数组是⼀种数组,数组中存放的是地址(指针)。
数组指针变量是指针变量?还是数组?
答案是:指针变量。(存放的应该是数组的地址,能够指向数组的指针变量。)
int (*p)[10];
p先和*结合,说明p是⼀个指针变量,然后指针指向的是⼀个⼤小为10个整型的数组。所以p是
⼀个指针,指向⼀个数组,叫数组指针。(由于[]的优先级高于*,故要用()保证*和p集合)
2.2 数组指针变量怎么初始化
数组指针变量是⽤来存放数组地址的,那怎么获得数组的地址呢?
int arr[10] = {0};
&arr;//得到的就是数组的地址

3. ⼆维数组传参的本质
前言:有⼀个⼆维数组的需要传参给⼀个函数的时候是这样写的。
#include<stdio.h>void print(int arr[][5], int r, int c)
{int i = 0;int j = 0;for (i = 0;i < r;i++){for (j = 0;j < c;j++){printf("%d ", arr[i][j]);}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };print(arr, 3, 5);return 0;
}
那么我们是否可以通过指针的方式实现二维数组的传参呢?
答案是肯定的。
首先,我们先来回忆下一维数组如何进行传参。

我们再来理解下二维数组:⼆维数组其实可以看做是每个元素是⼀维数组的数组,也就是⼆维
数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏,是个⼀维数组。
所以,根据⼆维数组的数组名表示的就是第⼀行的地址,那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀行这个⼀维数组的地址。
代码实现
void print(int (*p)[][5], int r, int c)
{int i = 0;for (i = 0;i < r;i++){int j = 0;for (;j < c;j++){//这段也可以写成printf("%d", *(*(p+i)+j));printf("%d ", p[i][j]);}printf("\n");}
}int main()
{int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };print(arr, 3, 5);return 0;
}
4. 函数指针变量
4.1 函数指针变量的创建
学习完数组指针后,根据类比关系,我们不难得出结论:
函数指针变量应该是⽤来存放函数地址的,未来通过地址能够调⽤函数的。
那么,我们该如何知道函数是否有地址呢?
int Add(int x, int y)
{return x + y;
}int main()
{//二者是等价的printf("%p\n", &Add);printf("%p\n", Add);return 0;
}

可以发现:函数名就是函数的地址。
那么有什么办法能将函数地址存起来呢?
仿效数组指针的方式,那肯定有函数指针变量将函数地址存起来(且此形式和数组指针类似)。
#include<stdio.h>int Add(int x, int y)
{return x + y;
}int main()
{int (*pf)(int, int) = &Add; //pf函数指针变量int ret = (*pf)(2, 3);//int ret = (pf)(2, 3);printf("%d\n", ret);return 0;
}

4.3 两段有趣的代码
《C陷阱和缺陷》有这样两个代码:
- (*(void (*)())0)();
- void (*signal(int , void(*)(int)))(int);
我们先来解读第一段代码:
int main()
{( * ( void (*)() ) 0 ) ();return 0;
}
我们先从0着手

1.将0强制类型转换成void(*) () 这种类型的函数指针,这个函数没有参数,返回类型是void.
2.然后去调用()地址处的函数.
第二段代码:

4.3.1 typedef 关键字
typedef 是⽤来类型重命名的,可以将复杂的类型,简单化。
例:若你觉得unsigned int 写起来不方便
typedef unsigned int uint;
那数组指针重命名又是咋样的呢?
typedef int(*parr_t)[5]
新的命名并不是写在最右边,而应该写在()里边。
同理,函数指针重命名也是如此
typedef void(*pfun_t)(int);
了解了typedef关键字后,我们清楚了它的作用是化繁为简(缺点:旁人并不能明白这个代码是啥类型,因此在旁边加上注释更有利于理解)。
我们可以将上面两段有趣的代码进行简化:
1. typedef void(*pfun_t)(int);2. pfun_t signal(int, pfun_t);
5. 函数指针数组的定义
上一节我们学习了指针的概念及使用,那么是否有一种方式能将函数的地址存放到数组中呢?
这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
int (*parr1[3])();
parr1先和[]结合,说明parr1是一个数组,其指向的内容是int (*)()类型的函数指针。
下一节会详细讲解函数指针数组的应用内容(明白其重要性)。
相关文章:
第四节——从深层剖析指针(让你不再害怕指针)
文章目录 1. 字符指针变量剑指offer例题 2. 数组指针变量2.1 数组指针变量是什么?2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质代码实现 4. 函数指针变量4.1 函数指针变量的创建4.3 两段有趣的代码4.3.1 typedef 关键字 5. 函数指针数组的定义 1. 字符指针变量…...
openpnp - 吸嘴校正失败的opencv参数分析
文章目录 openpnp - 吸嘴校正失败的opencv参数分析概述笔记阶段验证 - N2吸嘴校验完NT1NT2 阶段验证 - 底部相机高级校验完NT1NT2 参数比对保存 “阶段验证 - N2吸嘴校验完” 的NT1/NT2图像重建参数检测环境NT1ok的3个参数值NT1err的3个参数值NT2ok的3个参数值NT2err的3个参数值…...
【Python】Marmir 使用指南:Python 驱动的电子表格生成器
Marmir 是一个由 Python 驱动的电子表格生成工具,专门用于将 Python 数据结构(如字典、列表等)转换为电子表格文件(如 Excel)。Marmir 的设计目标是提供比传统电子表格库(如 xlwt)更强大和灵活的…...
深入理解 JavaScript 事件循环机制:单线程中的异步处理核心
深入理解 JavaScript 事件循环机制:单线程中的异步处理核心 JavaScript 是一门单线程的编程语言,也就是说它在同一时间只能执行一个任务。然而,现代 Web 应用经常需要处理大量的异步操作,如用户输入、网络请求、定时器等。为了确…...
Stream流的终结方法(二)——collect
1.Stream流的终结方法 2. collect方法 collect方法用于收集流中的数据放到集合中去,可以将流中的数据放到List,Set,Map集合中 2.1 将流中的数据收集到List集合中 package com.njau.d10_my_stream;import java.util.*; import java.util.f…...
【C语言系统编程】【第一部分:操作系统知识】1.1.操作系统原理
第一部分:操作系统知识 1.1 操作系统原理 1.1.1 进程管理 1.1.1.1 进程的概念与生命周期 进程是程序在计算机中的一次执行实例,包括了程序的代码、数据、以及运行的上下文环境。进程管理是操作系统的核心任务之一。 作用:管理所有执行中…...
基于Java+VUE+echarts大数据智能道路交通信息统计分析管理系统
大数据智能交通管理系统是一种基于Web的系统架构,通过浏览器/服务器(B/S)模式实现对城市交通数据的高效管理和智能化处理。该系统旨在通过集成各类交通数据,包括但不限于车辆信息、行驶记录、违章情况等,来提升城市管理…...
leetcode-42. 接雨水 单调栈
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…...
ThinkPHP和PHP的区别
文章目录 ThinkPHP和PHP的区别一、引言二、PHP简介1、第一步1.1、示例代码 三、ThinkPHP简介2、第二步2.1、特点2.2、示例代码 四、总结 ThinkPHP和PHP的区别 一、引言 在Web开发领域,PHP是一种广泛使用的开源脚本语言,而ThinkPHP则是一个基于PHP的MVC…...
clientWidth,offsetWidth,scrollHeight
clientWidth: offsetWidth: scrollHeight:...
SVN版本回退
SVN 版本回退三种方法: Update item to this version 假设我们的项目文件一共有8个版本,它版本号分别是1,2,3,4,5,6,7,8。 这个选项的作用是将文件版本更新到对应所选的…...
IDEA关联Tomcat
一、Tomcat服务器 web服务器,就是运行web项目的容器 即运行java代码的一个容器 webapp(web应用程序) --> 就是我们写的javaweb项目 Tomcat 是Apache 软件基金会(Apache Software Foundation)下的一个核心项目,免费开源、并支持Servlet 和J…...
MongoDB mongoose 的 save、insert 和 create 方法的比较
目录 save 方法 insert 方法 create 方法 使用会话和事务 总结 在本文中,我们将介绍 MongoDB 中使用 mongoose 操作 数据库时的三种常见方法:save、insert 和 create。这些方法可以用于将数据存储到 MongoDB 数据库中,并且在一定程度上具…...
Maven安装使用
说明:Maven是Apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。一般来说,它帮助我们管理依赖、构建项目。本文介绍在Windows系统下安装Maven。 下载&安装&验证 下载 首先,在Maven官网(https:…...
微信第三方开放平台接入本地消息事件接口报错问题java.security.InvalidKeyException: Illegal key size
先看报错: java.security.InvalidKeyException: Illegal key sizeat javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)at javax.crypto.Cipher.implInit(Cipher.java:805)at javax.crypto.Cipher.chooseProvider(Cipher.java:864)at javax.crypto.Cipher.in…...
如何只修改obsidian图片链接为markdown
如何只修改obsidian图片链接为markdown 前言插件配置 使用注意 前言 适合有一定了解obsidian用法和插件市场,还有相对路径的人 插件 在obsidian插件市场搜索—开梯子 配置 首先使用ctrlp打开命令面板,也可以在左侧通过图标打开命令面板,…...
AI不可尽信
看到某项目有类似这样的一段代码 leaves : make([]int, 10) leaves leaves[:0]没理解这样的连续两行,有何作用? 初始化一个长度和容量都为10的切片,接着把切片长度设置为0 即如下demo: (在线地址) package mainimport "fmt"func main() {leaves : make([]int, 1…...
[C++]使用纯opencv部署yolov11旋转框目标检测
【官方框架地址】 GitHub - ultralytics/ultralytics: Ultralytics YOLO11 🚀 【算法介绍】 YOLOv11是一种先进的对象检测算法,它通过单个神经网络实现了快速的物体检测。其中,旋转框检测是YOLOv11的一项重要特性,它可以有效地检…...
Python入门--函数
目录 1. 函数介绍 2. 函数的定义 3. 函数的参数 4. 函数的返回值 5. 函数说明文档 6. 函数的嵌套调用 7. 函数的作用域 (1). 局部变量 (2). 全局变量 (3). global关键字 1. 函数介绍 函数:是组织好的,可重复使用的,用来实现特定功能…...
winFrom界面无法打开
🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&am…...
电子电路中的“心脏”:电源
一、语言特性:Java 26 与模式匹配进化 1.1 Java 26 语言级别支持 IDEA 2026.1 EAP 最引人注目的变化之一,就是新增 Java 26 语言级别支持。这意味着开发者可以提前体验和测试即将在 JDK 26 中正式发布的语言特性。 其中最重要的变化是对 JEP 530 的全面支…...
深入解析Triton Inference Server的Backend机制与实战配置
1. Triton Inference Server的Backend机制揭秘 第一次接触Triton Inference Server时,我被它的Backend机制搞得一头雾水。直到在真实项目中踩过几次坑后,才真正理解它的精妙之处。简单来说,Backend就像是一个万能适配器,让Triton能…...
逆向思维:从资源困境到自由获取,猫抓如何重塑你的网页体验
逆向思维:从资源困境到自由获取,猫抓如何重塑你的网页体验 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾面对心仪…...
3步掌握DDrawCompat:轻松解决Windows老游戏兼容性的终极方案
3步掌握DDrawCompat:轻松解决Windows老游戏兼容性的终极方案 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/dd/…...
Pixel Epic · Wisdom Terminal 部署与压测:使用.accelerate库优化推理性能
Pixel Epic Wisdom Terminal 部署与压测:使用.accelerate库优化推理性能 1. 引言 如果你正在使用Pixel Epic Wisdom Terminal进行AI推理任务,可能会遇到性能瓶颈问题。今天我们就来聊聊如何用Hugging Face的.accelerate库来提升推理速度,…...
SecGPT-14B真实生成效果:漏洞成因解释、CVSS评分建议与PoC生成
SecGPT-14B真实生成效果:漏洞成因解释、CVSS评分建议与PoC生成 1. SecGPT-14B网络安全大模型简介 SecGPT是由云起无垠团队开发的开源大语言模型,专门针对网络安全领域优化。这个14B参数规模的模型采用vLLM框架部署,并通过Chainlit提供用户友…...
cool-admin(midway版)前端路由缓存:include与exclude配置策略
cool-admin(midway版)前端路由缓存:include与exclude配置策略 【免费下载链接】cool-admin-midway 🔥 cool-admin(midway版)一个很酷的后台权限管理框架,模块化、插件化、CRUD极速开发,永久开源免费,基于midway.js 3.x…...
Alpamayo-R1-10B参数详解:Top-p=0.98与Temperature=0.6组合的工程意义解析
Alpamayo-R1-10B参数详解:Top-p0.98与Temperature0.6组合的工程意义解析 1. 项目背景与技术架构 1.1 Alpamayo-R1-10B核心定位 Alpamayo-R1-10B是NVIDIA开发的自动驾驶专用视觉-语言-动作(VLA)模型,其核心设计目标是通过类人因果推理能力提升自动驾驶…...
adb工具箱下载,免费的ADB工具箱,手机投屏工具等推荐
Android Debug Bridge(ADB,安卓调试桥)是 Google 推出的跨平台命令行工具,属 Android SDK 平台工具核心组件,用于电脑与安卓设备(手机、平板、模拟器)通信Android Developers。 它采用客户端 -…...
5个简单步骤掌握LiteDB.Studio:免费开源的LiteDB数据库终极GUI管理工具
5个简单步骤掌握LiteDB.Studio:免费开源的LiteDB数据库终极GUI管理工具 【免费下载链接】LiteDB.Studio A GUI tool for viewing and editing documents for LiteDB v5 项目地址: https://gitcode.com/gh_mirrors/li/LiteDB.Studio 在当今数据驱动的软件开发…...
