10.3 指针进阶_代码分析
代码分析
- 9. 指针和数组代码解析
- 一维数组
- 字符数组
- 字符串
- 二维数组
- 10. 指针代码分析
- eg1
- eg2
- eg3
- eg4
- eg5
- eg6
- eg7
- eg8
10.1 指针进阶_数组指针
10.2 指针进阶_函数指针
9. 指针和数组代码解析
数组名arr是首元素地址
例外:
1. sizeof(arr),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
2. &arr,取出的是 数组的地址。&数组名,数组名表示 整个数组。
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址
一维数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//数组大小-->4*4=16 byte
printf("%d\n", sizeof(a+0));//a首元素地址,a+0-->4/8 byte
printf("%d\n", sizeof(*a));//a首元素地址,解引用*a,首元素大小-->4 byte
printf("%d\n", sizeof(a+1));//a+1-->4/8 byte
printf("%d\n", sizeof(a[1]));//第二个元素大小-->4 byte
printf("%d\n", sizeof(&a));//数组地址&a-->4/8 byte
printf("%d\n", sizeof(*&a));
//*&a --> a --> 数组地址&a,解引用*&a,数组大小大小-->16 byte
//&a --> int(*)[4] -->类型
// --> *&a --> a[4] 16 byte
printf("%d\n", sizeof(&a+1));//相对于&a,跳过了整个数组,地址大小-->4/8 byte
printf("%d\n", sizeof(&a[0]));//首元素地址-->4/8 byte
printf("%d\n", sizeof(&a[0]+1));//第二个元素地址-->4/8 byte
字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//整个数组大小 --> 6 byte
printf("%d\n", sizeof(arr+0));//首元素地址 --> 4/8 byte
printf("%d\n", sizeof(*arr));//首元素大小 --> 1 byte
printf("%d\n", sizeof(arr[1]));//第二个元素大小 --> 1 byte
printf("%d\n", sizeof(&arr));//数组地址 --> 4/8byte
printf("%d\n", sizeof(&arr+1));//相对于&arr,跳过了整个数组,地址-->4/8 byte
printf("%d\n", sizeof(&arr[0]+1));//首元素地址+1,第二个元素地址-->4/8 byteprintf("%d\n", strlen(arr));//strlen读到\0才结束,统计\0前字符串个数,随机值
printf("%d\n", strlen(arr+0));//首元素地址arr+0,随机值
printf("%d\n", strlen(*arr));//err,strlen参数部分需要传地址
//*arr是首元素a,a的ASCII码位97,strlen从97开始统计字符串长度,非法访问内存
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen(&arr));//&arr --> char(*)[6],数组地址,随机值
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//第二个元素地址,随机值
char arr[] = "abcdef";//[a b c d e f \0]
printf("%d\n", sizeof(arr));//数组大小 --> 7
printf("%d\n", sizeof(arr+0));//首元素地址 --> 4/8
printf("%d\n", sizeof(*arr));//首元素 --> 1
//*arr --> *(arr + 0) --> arr[0]
printf("%d\n", sizeof(arr[1]));//第二元素 --> 1
printf("%d\n", sizeof(&arr));//数组地址 --> 4/8
printf("%d\n", sizeof(&arr+1));//数组地址+1 --> 4/8
printf("%d\n", sizeof(&arr[0]+1));//第二元素地址 --> 4/8printf("%d\n", strlen(arr));//数组地址 6
printf("%d\n", strlen(arr+0));//首元素地址 6
printf("%d\n", strlen(*arr));//err 首元素a
printf("%d\n", strlen(arr[1]));//err 首元素a
printf("%d\n", strlen(&arr));//数组地址 6
printf("%d\n", strlen(&arr+1));//数组地址+1 random
printf("%d\n", strlen(&arr[0]+1));//第二元素地址 5
字符串
char* p = "abcdef";//[a b c d e f \0],p存放a的地址
printf("%d\n", sizeof(p));//指针p 4/8
printf("%d\n", sizeof(p+1));//b的地址 4/8
printf("%d\n", sizeof(*p));//a 1
printf("%d\n", sizeof(p[0]));//a 1
//*p --> *(p + 0) --> p[0]
printf("%d\n", sizeof(&p));//p的地址 4/8
//&p --> char**
printf("%d\n", sizeof(&p+1));//p的地址+1 4/8
printf("%d\n", sizeof(&p[0]+1));//b的地址+1 4/8printf("%d\n", strlen(p));//a的地址 6
printf("%d\n", strlen(p+1));//b的地址 5
printf("%d\n", strlen(*p));//err,a
printf("%d\n", strlen(p[0]));//err,a
printf("%d\n", strlen(&p));//p的地址 random
printf("%d\n", strlen(&p+1));//p的地址+1 random
printf("%d\n", strlen(&p[0]+1));//b的地址 5
二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//数组a大小 3*4*4=48
printf("%d\n",sizeof(a[0][0]));//[0][0]元素 4
printf("%d\n",sizeof(a[0]));//[0]行数组大小 4*4=16
//每行都是二维数组的一个元素,一维数组的数组
//a[0]是第一行一维数组的 数组名
printf("%d\n",sizeof(a[0]+1));//第1行数组第二个元素地址 4/8
printf("%d\n",sizeof(*(a[0]+1)));//第2行数组首元素大小 4
printf("%d\n",sizeof(a+1));//a是首元素地址,是第一行的地址,a+1是第2行地址 4/8
printf("%d\n",sizeof(*(a+1)));//第2行数组大小 4*4=16
printf("%d\n",sizeof(&a[0]+1));//&a是第1行的地址,a+1是第2行地址 4/8
printf("%d\n",sizeof(*(&a[0]+1)));//第2行数组大小 4*4=16
printf("%d\n",sizeof(*a));//第1行数组大小 4*4=16
//a 首元素地址,第1行地址
//*a 第1行
//*a --> *(a+0) --> a[0]
printf("%d\n",sizeof(a[3]));//第4行数组大小 4*4=16
//a[3] --> int [4]
//sizeof()只关注类型,不会计算
10. 指针代码分析
eg1
int main()
{ int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);//&a 取出 数组地址,&a+1 向后跳一个数组长度 的地址printf( "%d,%d", *(a + 1), *(ptr - 1));//(a+1) 首元素地址+1,第二元素地址。*(a+1) --> 2//ptr 是a[5]向后跳一个数组长度 的地址//(ptr - 1) 向前访问4byte --> 5return 0;
}
eg2
//结构体的大小是20个字节
struct Test
{ int Num;//4char *pcName;//1short sDate;//2char cha[2];//1short sBa[4];//2
}*p = (struct Test*)0x100000;
//结构体Test类型的变量大小是20个字节
int main()
{ printf("%p\n", p + 0x1);//跳过一个结构体 20byte//0x100000 + 0x000014 = 0x100014printf("%p\n", (unsigned long)p + 0x1);//整形+1byte --> 0x100001printf("%p\n", (unsigned int*)p + 0x1);//跳过+4byte --> 0x100004return 0;
}
eg3
int main()
{ int a[4] = { 1, 2, 3, 4 };//小端 [01 00 00 00| 02 00 00 00 00| 03 00 00 00| 04 00 00 00]int *ptr1 = (int *)(&a + 1);//&a 取出数组地址,&a+1 向后跳一个数组长度 的地址int *ptr2 = (int *)((int)a + 1);//(int)a a地址的值+ 1byte printf( "%x,%x", ptr1[-1], *ptr2);//%x --> 16进制打印//ptr1[-1] --> 4//*ptr2 --> 01 |00 00 00 02| -->2000000return 0;
}

eg4
#include <stdio.h>
int main()
{ int a[3][2] = { (0, 1), (2, 3), (4, 5) };//(0,1) --> 1. {0,1} is right//{{1,3}, {5,0}, {0,0}};int *p;p = a[0];//a是首元素地址,即第一行地址,a[0][0]的地址printf( "%d", p[0]);//p[0] --> *(p+0) -->*p --> 1return 0;
}
eg5
int main()
{ int a[5][5]; int(*p)[4]; p = a; printf( "%p,%d\n", &p[4][2] - &a[4][2], // -4&p[4][2] - &a[4][2]); return 0;
}

-4 -->
10000000 00000000 00000000 00000100
11111111 11111111 11111111 11111011
1111 1111 1111 1111 1111 1111 1111 1100
F F F F F F F C
0xFFFFFFFC
eg6
int main()
{ int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&a + 1);//数组地址+1,跳过一个数组的大小int *ptr2 = (int *)(*(a + 1));//第一行地址+1=第二行地址,*解引用 --> a[1][0]//a + 1 类型为 int (*)[5] 指向二维数组 a 的第二行//*(a + 1) 表示指向二维数组 a 第二行首元素的指针,它指向的是 a[1][0]//*(a + 1) --> a[1]数组名 --> 首元素地址&a[1][0]printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));//ptr1 -1 --> 10//ptr2 -1 --> 5return 0;
}
eg7
#include <stdio.h>
int main()
{ char* a[] = {"work","at","sangfor"};//char* p = "sangfor";//存放字符串首字符地址char** pa = a;//pa存放数组名pa++;// wo --> aprintf("%s\n", *pa);return 0;
}
eg8
int main()
{ char* c[] = {"ENTER","NEW","POINT","FIRST"};//指针数组,存放首字符地址char** cp[] = {c+3, c+2, c+1, c};char*** cpp = cp;printf("%s\n", **++cpp);//POINTprintf("%s\n", *--*++cpp+3);printf("%s\n", *cpp[-2]+3);printf("%s\n", cpp[-1][-1]+1);return 0;
}

printf("%s\n", ** ++cpp);//POINT 注意:cpp值已经更改

printf("%s\n", *--*++cpp+3);//ER

printf("%s\n", *cpp[-2]+3);//ST

printf("%s\n", cpp[-1][-1]+1);//EW

10.1 指针进阶_数组指针
10.2 指针进阶_函数指针
相关文章:
10.3 指针进阶_代码分析
代码分析 9. 指针和数组代码解析一维数组字符数组字符串二维数组 10. 指针代码分析eg1eg2eg3eg4eg5eg6eg7eg8 10.1 指针进阶_数组指针 10.2 指针进阶_函数指针 9. 指针和数组代码解析 数组名arr是首元素地址 例外: 1. sizeof(arr),计算整个数组的大小&…...
深入理解推理语言模型(RLM)
大语言模型从通用走向推理,万字长文解析推理语言模型,建议收藏后食用。 本文基于苏黎世联邦理工学院的论文《Reasoning Language Models: A Blueprint》进行整理,你将会了解到: 1、RLM的演进与基础:RLM融合LLM的知识广…...
在Nginx上配置并开启WebDAV服务的完整指南
在Nginx上配置并开启WebDAV服务的完整指南 如何在 Nginx 上开启 WebDAV 服务 要在 Nginx 上开启 WebDAV 服务,你需要配置 Nginx 以支持 WebDAV 请求。以下是详细的步骤: 1. 确保 Nginx 安装了 WebDAV 模块 Nginx 的 WebDAV 功能由 http_dav_module 模…...
大语言模型学习
大语言模型发展历程 当前国内外主流LLM模型 一、国外主流LLM LLaMA2 Meta推出的开源模型,参数规模涵盖70亿至700亿,支持代码生成和多领域任务适配57。衍生版本包括Code Llama(代码生成优化)和Llama Chat(对…...
夜天之书 #106 Apache 软件基金会如何投票选举?
近期若干开源组织进行换届选举。在此期间,拥有投票权的成员往往会热烈讨论,提名新成员候选人和治理团队的候选人。虽然讨论是容易进行的,但是实际的投票流程和运作方式,在一个成员众多的组织中,可能会有不少成员并不清…...
从Aurora看Xanadu可扩展模块化光量子计算机的现状与未来展望
从Aurora看Xanadu可扩展光量子计算机的现状与未来展望 一、引言 1.1 研究背景与意义 随着信息技术的飞速发展,经典计算机在许多领域取得了巨大的成功,但在面对一些复杂问题时,其计算能力逐渐接近极限。量子计算机作为一种新型计算设备,基于量子力学原理,能够实现并行计算…...
WPS如何添加论文中的文献引用右上角小标
给参考文献标号 1、将光标位于参考文献之前,然后点击如下图所示位置 2、点击相应的列表,然后点击确定 然后选中第一行,点击格式刷,刷一下其余行 在原文中插入右上角的引用标 1、使光标位于想插入引用光标处,点击交叉…...
如何理解语言模型
统计语言模型 先看语言模型,语言即自然语言,模型及我们要解决的某个任务。 任务一:判断哪句话出现的概率大 任务二:预判空缺的位置最有可能是哪个词 再看统计,统计即解决上述两个任务的解决方法。先对语句进行分词…...
准确-NGINX 1.26.2配置正向代理并编译安装的完整过程
NGINX 1.26.2 配置正向代理并编译安装的完整过程,使用了 ngx_http_proxy_connect_module 模块。 1. 环境准备 1.1 安装依赖 确保系统安装了以下必要的依赖: sudo yum install -y gcc gcc-c make pcre-devel zlib-devel openssl-devel1.2 下载 NGINX 源…...
企业如何将ERP和BPM项目结合提升核心竞争力
无论是实施ERP项目还是BPM项目,企业变革的根本目的的确是为了让企业变得更加强大,更具竞争力。 这就像是练武功,无论是学习少林拳还是太极拳,最终的目标都是为了强身健体,提升战斗力。 如何将ERP和BPM项目有效结合以及…...
Linux内核以太网驱动分析
1.网络接口卡接收和发送数据在Linux内核中的处理流程如下: 1. 网络接口卡(Network Interface Card, NIC) 作用:负责物理层的数据传输,将数据包从网络介质(如以太网线)读取到内存中,或…...
分布式微服务系统架构第92集:智能健康监测设备Java开发方案
加群联系作者vx:xiaoda0423 仓库地址:https://webvueblog.github.io/JavaPlusDoc/ https://1024bat.cn 嗯,用户需要为血压、血糖、尿酸和血酮测试仪编写产品描述,同时涉及Java开发。首先,我得确定他们的需求是什么。可…...
【推荐项目】023-游泳俱乐部管理系统
023 游泳俱乐部管理系统 游泳俱乐部管理系统概述 前端技术框架: 我们优雅地采用了Vue.js作为游泳俱乐部管理系统的前端基础框架。Vue.js以其轻盈、高效和易于上手的特点,为我们的用户界面带来了极致的流畅性和响应速度。通过Vue.js,我们为…...
Webpack常见配置实例
webpack实例 打包构建流程对应的常见配置 1. mode: development2. entry: ./src/index.js3. output4. module.rules5. Loader6. Plugin7. devServerwebpack.config.js webpack常见配置实例 配置详解 mode: ‘development’: 设置 Webpack 运行模式&am…...
C++核心编程之STL
STL初识:从零开始的奇幻冒险 1 STL的诞生:一场代码复用的革命 很久很久以前,在编程的世界里,开发者们每天都在重复造轮子。无论是数据结构还是算法,每个人都得从头开始写,仿佛在无尽的沙漠中寻找绿洲。直到…...
Mac mini M4安装nvm 和node
先要安装Homebrew(如果尚未安装)。在终端中输入以下命令: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示操作完成Homebrew的安装。 安装nvm。在终端中输入以下命令…...
Level DB --- 写流程架构
Level DB是高效的k-v数据库,接受多线程写,既要保证多线程写临界区安全,同时又要保证写流程的尽量高效性。 写入数据 Level DB 用一个deque用来衔接生产-消费模型。一个新的kv写入请求,会先将kv封装成Writer结构体。插入之前要先…...
【中等】707.设计链表
题目描述 你可以选择使用单链表或者双链表,设计并实现自己的链表。 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 如果是双向链表,则还需要属性 prev 以指示链表中的…...
深入理解Reactor Flux的生成方法
在Reactor框架中,Flux 是一个非常重要的概念,它用于表示一个可以产生多个事件的响应式流。通过 Flux 提供的多种生成方法,我们可以灵活地创建各种类型的流。本文将详细介绍 Flux.generate 方法的使用,并通过实例帮助读者更好地理解…...
next实现原理
Next.js 是一个基于 React 的 服务器端渲染(SSR) 和 静态生成(SSG) 框架,它的实现原理涉及多个关键技术点,包括 服务端渲染(SSR)、静态生成(SSG)、客户端渲染…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
