当前位置: 首页 > news >正文

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是首元素地址 例外&#xff1a; 1. sizeof(arr)&#xff0c;计算整个数组的大小&…...

深入理解推理语言模型(RLM)

大语言模型从通用走向推理&#xff0c;万字长文解析推理语言模型&#xff0c;建议收藏后食用。 本文基于苏黎世联邦理工学院的论文《Reasoning Language Models: A Blueprint》进行整理&#xff0c;你将会了解到&#xff1a; 1、RLM的演进与基础&#xff1a;RLM融合LLM的知识广…...

在Nginx上配置并开启WebDAV服务的完整指南

在Nginx上配置并开启WebDAV服务的完整指南 如何在 Nginx 上开启 WebDAV 服务 要在 Nginx 上开启 WebDAV 服务&#xff0c;你需要配置 Nginx 以支持 WebDAV 请求。以下是详细的步骤&#xff1a; 1. 确保 Nginx 安装了 WebDAV 模块 Nginx 的 WebDAV 功能由 http_dav_module 模…...

大语言模型学习

大语言模型发展历程 当前国内外主流LLM模型 ‌一、国外主流LLM‌ ‌LLaMA2‌ Meta推出的开源模型&#xff0c;参数规模涵盖70亿至700亿&#xff0c;支持代码生成和多领域任务适配‌57。衍生版本包括Code Llama&#xff08;代码生成优化&#xff09;和Llama Chat&#xff08;对…...

夜天之书 #106 Apache 软件基金会如何投票选举?

近期若干开源组织进行换届选举。在此期间&#xff0c;拥有投票权的成员往往会热烈讨论&#xff0c;提名新成员候选人和治理团队的候选人。虽然讨论是容易进行的&#xff0c;但是实际的投票流程和运作方式&#xff0c;在一个成员众多的组织中&#xff0c;可能会有不少成员并不清…...

从Aurora看Xanadu可扩展模块化光量子计算机的现状与未来展望

从Aurora看Xanadu可扩展光量子计算机的现状与未来展望 一、引言 1.1 研究背景与意义 随着信息技术的飞速发展,经典计算机在许多领域取得了巨大的成功,但在面对一些复杂问题时,其计算能力逐渐接近极限。量子计算机作为一种新型计算设备,基于量子力学原理,能够实现并行计算…...

WPS如何添加论文中的文献引用右上角小标

给参考文献标号 1、将光标位于参考文献之前&#xff0c;然后点击如下图所示位置 2、点击相应的列表&#xff0c;然后点击确定 然后选中第一行&#xff0c;点击格式刷&#xff0c;刷一下其余行 在原文中插入右上角的引用标 1、使光标位于想插入引用光标处&#xff0c;点击交叉…...

如何理解语言模型

统计语言模型 先看语言模型&#xff0c;语言即自然语言&#xff0c;模型及我们要解决的某个任务。 任务一&#xff1a;判断哪句话出现的概率大 任务二&#xff1a;预判空缺的位置最有可能是哪个词 再看统计&#xff0c;统计即解决上述两个任务的解决方法。先对语句进行分词…...

准确-NGINX 1.26.2配置正向代理并编译安装的完整过程

NGINX 1.26.2 配置正向代理并编译安装的完整过程&#xff0c;使用了 ngx_http_proxy_connect_module 模块。 1. 环境准备 1.1 安装依赖 确保系统安装了以下必要的依赖&#xff1a; sudo yum install -y gcc gcc-c make pcre-devel zlib-devel openssl-devel1.2 下载 NGINX 源…...

企业如何将ERP和BPM项目结合提升核心竞争力

无论是实施ERP项目还是BPM项目&#xff0c;企业变革的根本目的的确是为了让企业变得更加强大&#xff0c;更具竞争力。 这就像是练武功&#xff0c;无论是学习少林拳还是太极拳&#xff0c;最终的目标都是为了强身健体&#xff0c;提升战斗力。 如何将ERP和BPM项目有效结合以及…...

Linux内核以太网驱动分析

1.网络接口卡接收和发送数据在Linux内核中的处理流程如下&#xff1a; 1. 网络接口卡&#xff08;Network Interface Card, NIC&#xff09; 作用&#xff1a;负责物理层的数据传输&#xff0c;将数据包从网络介质&#xff08;如以太网线&#xff09;读取到内存中&#xff0c;或…...

分布式微服务系统架构第92集:智能健康监测设备Java开发方案

加群联系作者vx&#xff1a;xiaoda0423 仓库地址&#xff1a;https://webvueblog.github.io/JavaPlusDoc/ https://1024bat.cn 嗯&#xff0c;用户需要为血压、血糖、尿酸和血酮测试仪编写产品描述&#xff0c;同时涉及Java开发。首先&#xff0c;我得确定他们的需求是什么。可…...

【推荐项目】023-游泳俱乐部管理系统

023 游泳俱乐部管理系统 游泳俱乐部管理系统概述 前端技术框架&#xff1a; 我们优雅地采用了Vue.js作为游泳俱乐部管理系统的前端基础框架。Vue.js以其轻盈、高效和易于上手的特点&#xff0c;为我们的用户界面带来了极致的流畅性和响应速度。通过Vue.js&#xff0c;我们为…...

Webpack常见配置实例

webpack实例 打包构建流程对应的常见配置 1. mode: development​2. entry: ./src/index.js​3. output​4. module.rules​5. Loader​6. Plugin​7. devServerwebpack.config.js​ webpack常见配置实例 配置详解​ ​ mode: ‘development’:​ 设置 Webpack 运行模式&am…...

C++核心编程之STL

STL初识&#xff1a;从零开始的奇幻冒险 1 STL的诞生&#xff1a;一场代码复用的革命 很久很久以前&#xff0c;在编程的世界里&#xff0c;开发者们每天都在重复造轮子。无论是数据结构还是算法&#xff0c;每个人都得从头开始写&#xff0c;仿佛在无尽的沙漠中寻找绿洲。直到…...

Mac mini M4安装nvm 和node

先要安装Homebrew&#xff08;如果尚未安装&#xff09;。在终端中输入以下命令&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示操作完成Homebrew的安装。 安装nvm。在终端中输入以下命令&#xf…...

Level DB --- 写流程架构

Level DB是高效的k-v数据库&#xff0c;接受多线程写&#xff0c;既要保证多线程写临界区安全&#xff0c;同时又要保证写流程的尽量高效性。 写入数据 Level DB 用一个deque用来衔接生产-消费模型。一个新的kv写入请求&#xff0c;会先将kv封装成Writer结构体。插入之前要先…...

【中等】707.设计链表

题目描述 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的…...

深入理解Reactor Flux的生成方法

在Reactor框架中&#xff0c;Flux 是一个非常重要的概念&#xff0c;它用于表示一个可以产生多个事件的响应式流。通过 Flux 提供的多种生成方法&#xff0c;我们可以灵活地创建各种类型的流。本文将详细介绍 Flux.generate 方法的使用&#xff0c;并通过实例帮助读者更好地理解…...

next实现原理

Next.js 是一个基于 React 的 服务器端渲染&#xff08;SSR&#xff09; 和 静态生成&#xff08;SSG&#xff09; 框架&#xff0c;它的实现原理涉及多个关键技术点&#xff0c;包括 服务端渲染&#xff08;SSR&#xff09;、静态生成&#xff08;SSG&#xff09;、客户端渲染…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...