使用sizeof()和strlen()去计算【数组】和【指针】的大小

news2025/4/17 1:53:55

文章目录

  • 一、知识回顾
    • 1、回顾sizeof()、strlen的作用:
    • 2、数组和指针
    • 3、数组名
  • 二、sizeof()、strlen()的使用区别
    • 1、注意区别:
    • 2、一维数组与一级指针
    • 3、二维数组与二级指针
  • 三、总结回顾

一、知识回顾

1、回顾sizeof()、strlen的作用:

  • sizeof()是用来求取 变量 或者 类型 所占内存空间的大小(单位:字节)。
  • sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么。sizeof不是函数,是操作符
  • strlen()是一个库函数是专门用来计算 字符串 长度的,在对其进行调用前是需要包含头文件<string.h>。
  • strlen()函数是通过字符串结束标志 \0 来计算字符串长度的,但计算出来的字符串长度是不包括 \0 的,也就是说所谓的长度就是 \0 前字符的个数。strlen是函数

sizeof是一个运算符,用于计算一个变量或数据类型所占的字节数,不论变量中存储的数据是否为空。而strlen是一个函数,用于计算一个字符串中的字符数,不包括字符串末尾的空字符’\0’。
另外,sizeof可以用于计算任意数据类型的大小,包括基本数据类型和自定义数据类型。
而strlen只能用于计算字符串的长度。
因此,sizeof通常用于确定数组所占的存储空间,而strlen用于确定字符串的长度。

2、数组和指针

  • 数组 - 能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型。
  • 指针就是地址,大小都是4/8。(32位机器是4字节,64位机器是8字节)

3、数组名

  • 大部分情况下数组名是首元素地址
  • 2个例外
    sizeof(数组名) —— 数组名表示整个数组,计算的是整个数组的大小。(看数组名是否是单独放在sizeof()里面)
    &数组名 ————-数组名表示整个数组,取出的是数组的地址

二、sizeof()、strlen()的使用区别

1、注意区别:

  • 字符数组 - char arr1[]={‘a’,‘b’,‘c’,‘d’,‘e’,‘f’} ->[a,b,c,d,e,f]
  • 字符串数组 - char arr2[]=“abcdef” ->[a,b,c,d,e,f,/0]

  • sizeof()计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么
  • strlen()是针对字符串的,求的是字符串的长度,本质上统计的是/0之前出现的字符个数。

2、一维数组与一级指针


整型数组

	int a[] = { 1,2,3,4 };
	
	printf("%d\n", sizeof(a[1]));//4
	
	printf("%d\n", sizeof(a));//16 
	//sizeof(a) 就是数组名单独放在sizeof内部 计算的是整个数组的大小。

	printf("%d\n", sizeof(a + 0));// 4/8
	//a + 0   a不是单独放在sizeof()里面,则是数组首元素的地址,sizeof则是计算数组首元素地址的大小
	
	printf("%d\n", sizeof(*a));//4
	//a不是单独放在sizeof()里面,则是数组首元素的地址 *a == a[0],sizeof()则是计算首元素的大小。
	//*a -> *&a[0] -> a[0]

	printf("%d\n", sizeof(a + 1));// 4/8
	//a不是单独放在sizeof()里面,则是数组首元素的地址 -- int*
	//a+1 跳过1个整型,是第二个元素的地址 sizeof()是计算第二个元素地址的大小。

	printf("%d\n", sizeof(&a));// /4/8
	//&a - 取出的是数组的地址,但是数组的地址也是地址,地址的的大小就是4/8。
	//int (*pa)[4] = &a;

	printf("%d\n", sizeof(*&a));//16
	//等于sizeof(a)

	printf("%d\n", sizeof(&a+1));// 4/8
	//&a --> int (*)[4],取出的是数组的地址。
	//&a + 1 则要跳过一个数组。

	printf("%d\n", sizeof(&a[0]));
	//取出首元素地址,sizeof计算的是元素的地址4/8
	
	printf("%d\n", sizeof(&a[0]+1));//4/8
	//取出的是第二个元素的地址,sizeof()计算的是地址的大小。

编译器调试结果:
在这里插入图片描述


字符数组

	char arr[] = {'a','b','c','d','e','f'};
	
	printf("%d\n", sizeof(arr));//6
	
	printf("%d\n", sizeof(arr + 0));// 4/8
	//arr不单独放在sizeof里面,是数组首元素的地址 ,计算的大小为4/8
	
	printf("%d\n", sizeof(*arr));//1
	//arr不单独放在sizeof里面,arr是首元素地址,*arr 是首元素,大小为1
	
	printf("%d\n", sizeof(arr[1]));//元素'b'
	
	printf("%d\n", sizeof(&arr));// 4/8
	//&arr 是数组的地址,地址的大小的都是 4/8
	
	printf("%d\n", sizeof(&arr + 1));//4/8
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	
	//*****************************************
	
	printf("%d\n", strlen(arr));//随机值
	//arr数组首元素地址,找不到‘\0’,所以是计算的大小是随机值
	printf("%d\n", strlen(arr + 0));//随机值,同上
	
	printf("%d\n", strlen(*arr));//非法访问
	//strlen传入char*(地址)
	//*arr = 'a'——>(97)被当成地址,非法访问
	
	printf("%d\n", strlen(arr[1]));//非法访问,同上
	
	printf("%d\n", strlen(&arr));//随机值
	//找不到/0
		
	printf("%d\n", strlen(&arr + 1));//随机值 - 6
	printf("%d\n", strlen(&arr[0] + 0));//随机值 - 1

形成野指针非法访问
在编译器上调试可见,strlen接受的是char*类型,否则会报错
在这里插入图片描述


字符串数组

	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));//+1 跳过一个元素的地址,大小 4/8
	
	//******************************************************************

	printf("%d\n",strlen(arr));//arr表示首元素地址,计算得到数组大小为 6
	printf("%d\n",strlen(arr+0));//6,同上
	
	printf("%d\n",strlen(*arr));//非法访问
	printf("%d\n",strlen(arr[1]));//非法访问
	//strlen是传入char*地址,*arr和arr[1]是数组的元素,传给strlen会被当做地址,造成非法访问
	
	printf("%d\n",strlen(&arr));//&arr表示整个数组的大小,6
	printf("%d\n",strlen(&arr+1));//数组的地址 +1后就找不到 /0 ,大小为随机值
	printf("%d\n",strlen(&arr[0]+1));//从第二个元素开始算,大小为5


指针

	char* p="abcdef";
	printf("%d\n",sizeof(p));//4/8
	//指针变量p 存放着的是地址,所以大小为4/8
	
	printf("%d\n",sizeof(p+1));//字符’b‘的地址,大小为4/8
	
	printf("%d\n",sizeof(*p));
	//解引用的一个char类型元素,大小为1
	
	printf("%d\n",sizeof(p[0]));//1
	//p[0] = *(p+0)
	printf("%d\n",sizeof(&p));//4/8
	
	printf("%d\n",sizeof(&p+1));
	//+1跳过一个char*地址,还是地址,大小还是4/8

	//********************************************

	printf("%d\n",strlen(p));//大小为 6
	printf("%d\n",strlen(p+1));//p+1是'b'的地址,从'b'开始算,大小为5
	printf("%d\n",strlen(*p));//*p为'a',不是地址,非法访问
	
	printf("%d\n",strlen(&p));//随机值
	//&p取的是变量p的地址,不是p里面存放的地址,所以无法找打字符串
	printf("%d\n",strlen(&p+1));//随机值,同上
	
	printf("%d\n",strlen(&p[0]+1));//大小为 5
	//p[0]是’a‘,&p[0]去'a'的地址,+1的'b'的地址,从'b'开始计算
	

3、二维数组与二级指针

整型数组

	int a[3][4]={0};//三行四列的数组
	printf("%d\n",sizeof(a));//4*3*4=48
	//a这个数组名单独放在sizeof里面,表示整个数组,计算的是整个数组的大小
	
	printf("%d\n",sizeof(a[0][0]));//第一行第一个元素,大小4字节
	
	printf("%d\n",sizeof(a[0]));//16
	//a[0] 是第一行的数组名,这是数组名单独放在sizeof内部,计算的是第一行数组的大小
	
	printf("%d\n",sizeof(a[0]+1));//4/8
	//a[0]不是单独放在sizeof内部,表示的是首元素的地址。即第一行第一个元素的地址,相当于&a[0][0]
	//a[0]+1 是第一行第二个元素的地址,相当于&a[0][1]
	
	printf("%d\n",sizeof(a+1));//4/8
	//a作为二维数组的数组名,并非单独放在sizeof内部,所以表示首元素是地址
	//二维数组的首元素是第一行,这里的a就是第一行的地址
	//a+1是跳过第一行,指向第二行
	
	printf("%d\n",sizeof(*(a+1)));//16
	//*(a+1) -> a[1],计算的是第二行的大小
	
	printf("%d\n",sizeof(&a[0]+1));//4/8
	//&a[0]是第一行的地址
	//&a[0]+1是第二行的地址
	
	printf("%d\n",sizeof(*(&a[0]+1)));//表示第二行,大小为16
	printf("%d\n",sizeof(*a));//16
	//*a --> *(a+0)表示第一行,大小为16
	

三、总结回顾

  • sizeof(数组名),这里的数组名表示整个数组,计算的是数组的大小。
  • &数组名,这里的数组名表示整数数组,取出的是整个数组的地址。
  • 除此之外所有的数组名都表示首元素的地址。

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

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

相关文章

【18】c++11新特性 —>线程同步

线程同步&#xff1a;线程同步就是让多个线程按顺序访问临界区域&#xff0c;只有在当前线程访问临时区结束后&#xff0c;下一个线程才能继续访问。&#xff08;临界区加锁即可&#xff09; #include <iostream> #include <chrono> #include <thread> #inc…

【ZYNQ】裸机 PS + PL 双网口实现之 SDK 程序设计

涉及 lwip 库文件及 ZYNQ 配置相关可参考以下文章&#xff1a; 【ZYNQ】裸机 PS PL 双网口实现之 LWIP 库文件修改 【ZYNQ】裸机 PS PL 双网口实现之 ZYNQ 配置 工程配置 启动 SDK &#xff0c;创建模板工程&#xff0c;配置 BSP。 勾选 lwip141 库。 对 lwip 做如下配置…

Flink—— Data Source 介绍

Data Source 简介 Flink 做为一款流式计算框架&#xff0c;它可用来做批处理&#xff0c;即处理静态的数据集、历史的数据集&#xff1b;也可以用来做流处理&#xff0c;即实时的处理些实时数据流&#xff0c;实时的产生数据流结果&#xff0c;只要数据源源不断的过来&#xff…

在IDEA中配置Web开发环境

一、idea配置Web开发环境 第一步&#xff1a;下载并安装Tomcat服务器&#xff08;建议放根目录&#xff0c;完整路径中不要出现中文&#xff09; 第二步&#xff1a;打开IDEA&#xff0c;新建java项目 第三步&#xff1a;为项目添加Web应用 在项目上右键➡️选择“Add Framew…

算法通关村第七关-黄金挑战二叉树迭代遍历

大家好我是苏麟 , 今天带来二叉树的迭代遍历 . 二叉树的迭代遍历 前序编列 描述 : 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 题目 : LeetCode 二叉树的前序遍历 : 144. 二叉树的前序遍历 分析 : 前序遍历是中左右&#xff0c;如果还有左子树就一…

交叉编译中常见错误解决方法

目录 程序运行基础知识 编译程序时去哪找头文件&#xff1f; 链接时去哪找库文件&#xff1f; 运行时去哪找库文件&#xff1f; 运行时不需要头文件&#xff0c;所以头文件不用放到板子上 常见错误的解决方法 头文件问题 库文件问题 运行问题 交叉编译程序的万能命令 …

YOLOv5-6.1源码详解之损失函数loss.py

目录 1 目标检测结果精确度的度量 2 YOLOv5-6.1损失函数 2.1 classification类别损失 2.2 confidence置信度损失 2.3 localization定位损失 3 YOLOv5-6.1损失函数loss.py代码解析 3.1 class ComputeLoss 3.1.1 __init__ 3.1.2 build_targets 3.1.3 _call__ 3.2 smo…

说说React diff的原理是什么?

一、是什么 跟Vue一致&#xff0c;React通过引入Virtual DOM的概念&#xff0c;极大地避免无效的Dom操作&#xff0c;使我们的页面的构建效率提到了极大的提升 而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处 传统diff算法通过循环递归对节点进行依…

Semantic-Guided Zero-Shot Learning for Low-Light ImageVideo Enhancement

论文阅读之无监督低光照图像增强 Semantic-Guided Zero-Shot Learning for Low-Light Image/Video Enhancement 代码&#xff1a; https://github.com/ShenZheng2000/SemantiGuided-Low-Light-Image-Enhancement 在低光条件下增加亮度的一个可行方法是使用更高的ISO或更长时间…

AI:76-基于机器学习的智能城市交通管理

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

leetcode:LCP 11. 期望个数统计(python3解法)

难度&#xff1a;简单 某互联网公司一年一度的春招开始了&#xff0c;一共有 n 名面试者入选。每名面试者都会提交一份简历&#xff0c;公司会根据提供的简历资料产生一个预估的能力值&#xff0c;数值越大代表越有可能通过面试。 小 A 和小 B 负责审核面试者&#xff0c;他们均…

计算机二级公共基础

知识点 1.树 树的最大层次&#xff08;最长路径的长度&#xff09;称为树的深度 二叉树的后件最多不超过两个 满二叉树&#xff1a;除最后一层每一层的所有节点都有两个子节点。&#xff08;满二叉树一定是完全二叉树&#xff09; 完全二叉树&#xff1a;所有节点均达到最大数…

显著提升!| (WOA)融合模拟退火和自适应变异的混沌鲸鱼优化算法应用于函数寻优

鲸鱼优化算法(whale optimization algorithm,WOA)是由Mirjalili和Lewis[1]于2016年提出的一种新型群体智能优化搜索方法,它源于对自然界中座头鲸群体狩猎行为的模拟&#xff0c;与其它群体智能优化算法相比&#xff0c;WOA算法结构新颖, 控制参数少&#xff0c;在许多数值优化和…

JavaScript使用Ajax

Ajax(Asynchronous JavaScript and XML)是使用JavaScript脚本&#xff0c;借助XMLHttpRequest插件&#xff0c;在客户端与服务器端之间实现异步通信的一种方法。2005年2月&#xff0c;Ajax第一次正式出现&#xff0c;从此以后Ajax成为JavaScript发起HTTP异步请求的代名词。2006…

【论文阅读】DALL·E: Zero-Shot Text-to-Image Generation

OpenAI第一代文本生成图片模型 paper&#xff1a;https://arxiv.org/abs/2102.12092 DALLE有120亿参数&#xff0c;基于自回归transformer&#xff0c;在2.5亿 图片-文本对上训练的。实现了高质量可控的text to image&#xff0c;同时也有zero-shot的能力。 DALL-E没有使用扩…

汽车螺丝扭力标准/汽车常见螺栓扭矩参照

汽车螺丝扭力标准参照表如下&#xff1a; 1、支座与车身螺栓(13MM)--25Nm&#xff1b; 2、支座与车身螺栓(18MM)--40Nm90度/50Nm&#xff1b; 3、支座与发动机支座螺栓(18Mm)--100Nm&#xff1b; 4、支座与车身螺栓(13MM)--25Nm&#xff1b; 5、支座与车身螺栓(18MM)--40N…

【Rust日报】2023-11-08 RustyVault -- 基于 rust 的现代秘密管理系统

RustyVault -- 基于 rust 的现代秘密管理系统 RustyVault 是一个用 Rust 编写的现代秘密管理系统。RustyVault 提供多种功能&#xff0c;支持多种场景&#xff0c;包括安全存储、云身份管理、秘密管理、Kubernetes 集成、PKI 基础设施、密码计算、传统密钥管理等。RustyVault 可…

面试10000次依然会问的【线程池】,你还不会?

线程池的基本概念 线程池是一种基于池化技术的线程使用方式&#xff0c;它允许我们有效地管理和复用线程&#xff0c;减少线程的创建和销毁的开销&#xff0c;从而提高系统的响应速度。在Java中&#xff0c;线程池的管理主要通过ThreadPoolExecutor类来实现。 线程池的定义与…

docker可视化

什么是portainer&#xff1f; portainer就是docker图形化界面的管理工具&#xff0c;提供一个后台面板供我们操作 目前先用portainer(先用这个)&#xff0c;以后还会用到Rancher(CI/CD在用) 1.下载portainer 9000是内网端口&#xff0c;8088是外网访问端口 docker run…

19 数据中心详解

1、数据中心的概念 其实平时我们不管是看新闻&#xff0c;视频&#xff0c;下载文件等&#xff0c;最终访问的目的地都是在数据中心里面。数据中心存放的是服务器&#xff0c;区别于我们平时使用的笔记本或者台式机。 机架&#xff1a;数据中心的服务器被放在一个个叫作机架&…