C语言sizeof操作符与strlen函数

news2024/12/24 9:54:26

1.sizeof与strlen的介绍

(1).sizeof

  • 计算变量的内存空间大小
  • 底层实际上是对变量类型的计算。
  • 是一个单目操作符,不是函数,后面的括号可以省略

(2).strlen 

函数原型
  • strlen是一个函数,返回的size_t类型的数据,头文件为string.h
  • 计算字符串'\0'前的字符个数,计算字符长度
  • 如果没有找到'\0'就继续往下找,通常对于没有'\0'的字符生成的是一个随机值
  • 函数通过首元素的地址往下找。

(3)sizeof与strlen对比 

对比sizeofstrlen
所属类型单目操作符库函数
计算内容

元素的内存空间大小

(单位:字节)

元素的个数
特性

1.括号可有可无

2.只关注变量的类型

3.不关注变量中的数据是啥

1.通过地址往后找

2.找到' \0 '后结束

3.找不到' \0 '一直向后找

2.sizeof和strlen的使用

下面通过使用sizeof和strlen对数组进行操作的例子来加深我们的理解吧

在举例前我们先要知道数组和sizeof(数组名),以及取地址数组名的区别:

对比一维数组的数组名,以arr[10]为例:

对比arrsizeof(arr)&arr
含义数组首元素地址计算整个数组的大小整个数组的地址
条件除了后面两种情况arr单独在sizeof内部任何时候

 再对比一下二维数组的数组名,以arr[10][10]为例:

arr第一行数组的地址
arr[0]

第一行数组名,是数组名就等于第一行第一个元素的地址

&arr整个数组的地址
&arr[0]第一行数组的地址
sizeof(arr)整个数组的大小
sizeof(arr[0])第一行数组的大小

总结:

  1. 只要arr不单独存在sizeof内部或者被取地址,那么都是首元素的地址。
  2. 二维数组的数组名是第一行数组的地址,二维数组使用下标访问符一次是某一行数组的名字,同时这种情况也要除去单独在sizeof内部和取地址。

(1)一维整形数组和sizeof

题目以及分析:
int a[] = { 1,2,3,4 };
printf("%zd\n", sizeof(a));//数组总大小,4*4=16字节
printf("%zd\n", sizeof(a + 0));//数组首元素的地址,首地址+0=首地址,地址的大小是的4/8字节
printf("%zd\n", sizeof(*a));//a是数组首元素的地址,*a就是首元素,计算的就是首元素的大小,整形4字节
printf("%zd\n", sizeof(a + 1));//a是数组首元素的地址,地址+1跳过一个元素,那就是第二个元素的地址,4/8
printf("%zd\n", sizeof(a[1]));//第二个元素,整形int,4字节
printf("%zd\n", sizeof(&a));//&a取出的是数组整个元素的地址,还是地址,4/8

/*****************************重点******************************/
printf("%zd\n", sizeof(*&a));//不是单独的&a,a表示首元素的地址,&a是取出首元素的地址的地址,再解引用就是首元素的地址,4/8
printf("%zd\n", sizeof(&a + 1));//取地址a是整个数组的地址,+1跳过整个数组,地址是数组末尾元素后面的地址的,
							  //实际还是地址,sizeof只关注类型,不关注指针是否越界,
							  // 换句话说这个指针并没有被使用只是计算大小,所以是可以计算的
/****************************************************************/

printf("%zd\n", sizeof(&a[0]));//取出首元素的地址,是地址,4/8
printf("%zd\n", sizeof(&a[0] + 1));//取出首元素的地址,地址+1,跳过一个元素,第二个元素的地址,是地址,4/8
//正确率:错1,printf("%d\n", sizeof(*&a));
//正确理解1:&a是整个数组的地址,与&a单独作用无关,&a取出的就是整个数组的地址,解引用就是拿出整个数组,整个数组的大小就是16
//理解2:解引用*和取地址&相互抵消,剩下a,就是数组名,sizeof(a)==16
答案: 

(2).使用大括号存储的字符数组 

A.sizeof

题目以及分析:
	//字符数组,字符单个存储,只有abcdef这六个元素,没有'\0'
	printf("%zd\n", sizeof(arr));//sizeof操作时,单独只有个数组名时,整个数组的大小,1*6=6字节
	printf("%zd\n", sizeof(arr + 0));//arr表示数组首元素的地址,首元素的地址+0,就是首元素的地址,是地址,大小就是4/8
	printf("%zd\n", sizeof(*arr));//arr是数组首元素的地址,解引用首元素的地址就是首元素,字符char,1字节
	printf("%zd\n", sizeof(arr[1]));//第二元素,字符char,1字节
	printf("%zd\n", sizeof(&arr));//&arr是整个元素的地址,是地址,大小就是4/8
	printf("%zd\n", sizeof(&arr + 1));//整个数组的地址,地址是数组指针类型,+1跳过1个数组的大小,就是末元素后元素的地址,是地址,4/8
	printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0]是取出首元素的地址,地址是字符指针,+1跳过一个元素,指向第二个元素,是地址,大小4/8
	//正确率:全对
答案: 

B.strlen

题目以及分析:
char arr[] = { 'a','b','c','d','e','f' };
//字符数组,字符单个存储,只有abcdef这六个元素,没有'\0'
printf("%zd\n", strlen(arr));//strlen函数计算字符个数,给的数组首元素的地址,strlen从这后向找,无\0,随机值
printf("%zd\n", strlen(arr + 0));//首元素地址+1还是首元素的地址,从首元素开始向后找,无\0,随机值
/*重点*/
//printf("%zd\n", strlen(*arr));//arr表示首元素的地址,首元素的地址解引用,得到第一个元素,就是a,
//因为,strlen函数的参数是地址,那么字符a就被转为它的ASCII码值,97,那么地址就是97,
//但是因为这个地址是个特殊地址,无法被访问,所以报错
//printf("%zd\n", strlen(arr[1]));//arr[1]表示第二个元素,那就是字符b,
//同样也被转为ASCII码值对应的数字98,地址98也是特殊地址无法访问
printf("%zd\n", strlen(&arr));//&arr是整个数组的地址,是数组指针,那就被转为字符指针,指针是首元素的地址,无\0,随机值
printf("%zd\n", strlen(&arr + 1));//&arr是整个数组的地址,+1跳过整个数组,
//地址就到末元素后面一个元素的地址,从这开始向后找,后面找不到'\0',就一直找下去,生成的随机值,随机值比第一个开始找的多6个
printf("%zd\n", strlen(&arr[0] + 1));//首元素的地址+1,到第二个元素的地址,从第二个元素向后找,没有斜杠0,随机值,
//比从第一个开始找的多一个数
//正确率:全对
//注意:1.特殊地址无法访问,会报错;2.大括号存字符无\0随机值
答案: 

(3).使用字符串存储的字符数组

A.sizeof

题目以及分析:
char arr[] = "abcdef";
//字符串存储,数组大小也没有限定,存完字符后后再存了一个'\0'
printf("%zd\n", sizeof(arr));//计算的是整个数组的内存大小,7*1=7个字节
printf("%zd\n", sizeof(arr + 0));//arr是数组首元素的地址,首元素的地址+0=首元素的地址,地址的大小,4/8
printf("%zd\n", sizeof(*arr));//arr是数组首元素的地址,首元素的地址解引用得到的是首元素,首元素的大小char,1个字节
printf("%zd\n", sizeof(arr[1]));//arr[1]是首元素,char,1个字节
printf("%zd\n", sizeof(&arr));//&arr是取出整个数组的地址,是地址,4/8
printf("%zd\n", sizeof(&arr + 1));//&arr是取出的整个数组的地址,数组指针类型,地址+1跳过整个数组,
//那就是末元素的下一个元素地址,是地址,4/8
printf("%zd\n", sizeof(&arr[0] + 1));//&arr[0]取出的是首元素的地址,首元素的地址+1跳过1个元素,那就是第二个元素的地址,是地址,4/8
//正确率:全对
答案: 

B.strlen

题目以及分析:
char arr[] = "abcdef";
//字符串存储,数组大小也没有限定,存完字符后后再存了一个'\0'
printf("%d\n", strlen(arr));//arr是首元素的地址,计算'\0'前的元素个数,6个
printf("%d\n", strlen(arr + 0));//arr是首元素的地址,+0还是首元素的地址,计算出6个元素
//printf("%d\n", strlen(*arr));//arr是首元素的地址,解引用得到首元素,字符a转换为ASCII码值97,97是个特殊地址无法访问,报错。
//printf("%d\n", strlen(arr[1]));//同上,arr[1]='b',转为ASCll码值98,特殊地址无法访问
printf("%d\n", strlen(&arr));//&arr取出的是整个数组的地址,而strlen的参数接收的是char*类型,就会进行强制类型转换,
//而整个数组的地址就是首元素的地址,那就是首元素的地址,从后计算得到6个元素
printf("%d\n", strlen(&arr + 1));//&arr取出的是整个数组的地址,+1就会跳过整个数组,到达\0后面
//拿到后面这个元素地址,注意这里操作的任然是地址,从这向后找,找不到'\0',随机值
printf("%d\n", strlen(&arr[0] + 1));//&arr[0],第一个元素的地址,+1第二个元素的地址,从第二个元素开始计算,5个
//正确率:全对
答案: 

(4).使用指针存储常量字符串

A.sizeof

题目以及分析:
char* p = "abcdef";//首元素的地址
printf("%zd\n", sizeof(p));//p是一个指针,大小4/8
printf("%zd\n", sizeof(p + 1));//p+1跳过一个元素,b的地址,是地址,4/8
printf("%zd\n", sizeof(*p));//*p得到'a',char类型数据,1个字节
printf("%zd\n", sizeof(p[0]));//p[0]==*(p+0)==数组名[0]==第一个元素,char类型,1个字节
printf("%zd\n", sizeof(&p));//&p,取出第一个元素的地址的地址,是地址,4/8
printf("%zd\n", sizeof(&p + 1));//&p,取出第一个元素的地址的地址,+1跳过一个地址,还是地址,4/8
printf("%zd\n", sizeof(&p[0] + 1));//&p[0]==&p[0]==&*(p+0)=p,是地址,4/8
//正确率:全对
答案: 

B.strlen

题目以及分析:
char* p = "abcdef";//首元素的地址,常量字符串后面也有\0
printf("%zd\n", strlen(p));//从首元素开始计算,6个元素
printf("%zd\n", strlen(p + 1));//首元素地址+1,从第二个元素开始计算,5个元素
//printf("%d\n", strlen(*p));//*p是'a',转为ACSII码值97,特殊地址,无法访问,报错
//printf("%d\n", strlen(p[0]));//p[0]==数组名[0]==*(p+0)==*p=='a',同上,报错
printf("%zd\n", strlen(&p));//&p,取出地址的地址,从后计算,找不到'\0',随机值
printf("%zd\n", strlen(&p + 1));//&p,取出地址的地址,+1跳过一个地址,从后计算,找不到'\0',随机值
printf("%zd\n", strlen(&p[0] + 1));//&p[0]+1==&*(p+0+1==p+1,从第二个元素向后计算,5
//正确率:全对
答案: 

(5).二维数组和sizeof

B.strlen

题目以及分析:
//二维数组数组名是第一行数组的地址,&数组名是取出整个数组的地址
int a[3][4] = { 0 };
printf("%zd\n", sizeof(a));//数组单独存在sizeof的内部,计算的是整个数组的大小,3*4*4=48
printf("%zd\n", sizeof(a[0][0]));//第一行第一列元素啊,int类型,4个字节
//重点//
printf("%zd\n", sizeof(a[0]));//第一行数组名字,单独放在sizeof的内部,计算第一列数组的大小,4*4=16
printf("%zd\n", sizeof(a[0] + 1));//第一行第一个元素地址+1==第一行第二列元素地址,4/8
printf("%zd\n", sizeof(*(a[0] + 1)));//解引用第二列数组,计算数组大小,4*4=16
//
printf("%zd\n", sizeof(a + 1));//a是第一行的地址,+1第二行,还是地址,4/8
printf("%zd\n", sizeof(*(a + 1)));//a是第一行数组的地址,+1第二行,解引用是数组,4*4=16
printf("%zd\n", sizeof(&a[0] + 1));//取出第一行的地址,+1第二行的地址,是地址,4/8
printf("%zd\n", sizeof(*(&a[0] + 1)));//第二行的地址解引用,第二行数组大小,4*4=16
printf("%zd\n", sizeof(*a));//a是第一行的地址,解引用是第一行的数组大小,4*4=16
printf("%zd\n", sizeof(a[3]));//第四行数组名单独在sizeof内部,计算的是数组大小,虽然越界,但没使用,底层是类型,4*4=16
//正确率:错一个,printf("%d\n", sizeof(*(a[0] + 1));
错误分析:解引用第二列数组,计算数组大小,4*4=16
正确分析:第一行数组名表示第一行数组第一个元素的地址,得到元素,int,4个字节
答案: 

总的来说只要理解了sizeof和strlen的作用,知道数组名不同场景下所表示的含义这种题目就很简单啦!!!


本章内容结束,我们下章见,拜拜!!!

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

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

相关文章

运维自动化之——Ansible

一、自动化运维 1、通过xshell实现自动化运维 xshell提供会话窗口同步发送命令功能,但是必须将多台机器同时通过xshell窗口连接然后输入命令,如下点击xshell的工具---发送输入--到所有窗口或者指定窗口。 2、Ansible简介 Ansible是基于模块工作的&…

TSINGSEE青犀视频AI方案:数据+算力+算法,人工智能的三大基石

背景分析 随着信息技术的迅猛发展,人工智能(AI)已经逐渐渗透到我们生活的各个领域,从智能家居到自动驾驶,从医疗诊断到金融风控,AI的应用正在改变着我们的生活方式。而数据、算法和算力,正是构成…

安装Android Studio遇到Unable to access Android SDK add-on list的错误

第一次安装android studio的时候,提示:unable to access Android sdk add-on list 解决办法 这个错误一般是android studoi代理没有设置导致的,需要在setting里面设置: 点击Android Studio - Preferences,在 Appeara…

开源导出html表格项目-easyHtml

开源导出html表格项目-easyHtml 背景介绍 背景 项目的由来,在面试的过程中,发现这个需求(导出html表格)比较常见,同时也引起我的兴趣,所以就有了开源项目easyHtml第一个版本 介绍 功能 支持自定义表格标…

算法-图的存储,图的转置,拓扑排序

1.图的存储 图用来对关系建模.图是节点和边构成的集合.节点反映图的元素集合,边反映图的元素集合中元素间的关系. 上述是由五个节点,三条边构成的结构.我们可以用图对其建模. 对由节点&#x…

TeXLive 2023+TeXstudio下载与安装

一. TeXLive 2023下载与安装 TeX Live 是一种 Tex 语言的发行版本,就是相当于 C 语言的编辑(VisualC++),但是这种编辑器的操作方式比较复杂,需要在 cmd 中输入命令操作,没有软件界面,而 Texstudio 正好解决了这个问题。清华大学镜像文件:https://mirrors.tuna.tsinghua…

Linux内核有什么之块设备驱动有什么第二回 —— 块设备驱动初始化流程 vs 字符设备驱动初始化流程

接前一篇文章:Linux内核有什么之块设备驱动有什么第一回 —— 概述及框架 本文内容参考: 34 | 块设备(上):如何建立代理商销售模式?-趣谈Linux操作系统-极客时间 Linux内核——块设备总结_linux do_open-…

探索人工智能的现状与未来:机遇与挑战

🍎个人博客:个人主页 🏆个人专栏:日常聊聊 ⛳️ 功不唐捐,玉汝于成 目录 正文 人工智能的现状 人工智能的应用领域 人工智能的未来 人工智能面临的挑战 我的其他博客 正文 人工智能(AI&#xff09…

空间计算综合指南

空间计算(spatial computing)是指使人类能够在三维空间中与计算机交互的一组技术。 该保护伞下的技术包括增强现实(AR)和虚拟现实(VR)。 这本综合指南将介绍有关空间计算所需了解的一切。 你将了解 AR、VR…

【yolov8和yolov5】用命令快速着手训练

文章目录 1.yolov81.1.创建conda环境1.2.下载代码和环境1.3.YOLOv8训练、自测和预测的代码及解释1.3.1. YOLOv8 训练代码:1.3.2.yolov8 自测代码:1.3.3.yolov8 推理代码:1.3.4.注意: 2.yolov52.1.创建conda环境2.2.下载代码和环境…

在项目管理中,如何更好地协同团队成员,提高团队合作效率?

在项目管理中,协同团队成员并提高团队合作效率是确保项目成功实施的关键。以下是一些建议,有助于更好地协同团队成员,提高团队合作效率: 一、明确角色与责任 为每个团队成员分配明确的角色和职责,通过制定详细的任务…

Kafka MQ 如何处理请求

Kafka MQ 如何处理请求 元数据请求 客户端怎么知道该往哪里发送请求呢? 客户端使用了另一种请求类型,也就是元数据 请求。这种请求包含了客户端感兴趣的主题列表。服务器端的响应消息里指明了这些主题 所包含的分区、每个分区都有哪些副本,以及哪个副…

基于java+springboot开发的计算机毕业设计网文论坛管理系统设计与实现【附源码】

基于javaspringboot开发的计算机毕业设计网文论坛管理系统设计与实现【附源码】 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联…

HTML静态网页成品作业(HTML+CSS)——游戏战地介绍设计制作(4个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有4个页面。 二、作品演示 三、代…

视频AI方案:数据+算力+算法,人工智能的三大基石

背景分析 随着信息技术的迅猛发展,人工智能(AI)已经逐渐渗透到我们生活的各个领域,从智能家居到自动驾驶,从医疗诊断到金融风控,AI的应用正在改变着我们的生活方式。而数据、算法和算力,正是构…

Matplotlib中的子图:规划绘图的指南和工具

导 读 我最近从事一个项目,需要在 matplotlib 中进行一些微调的子图和叠加。虽然我对制作基本的可视化感到很舒服,但我很快发现我对子图系统的理解没有达到标准。于是回到基础知识,并花了一些时间阅读文档并在 Stack Overflow 上搜索相关示例…

算法-前缀和-562. 壁画

题目 思路 被毁掉的墙段一定只与一段还未被毁掉的墙面相邻只能从两头坏,因为如果从中间坏的话,毁掉的墙就和两段未被毁掉的墙面相邻了,画了的墙是坏不了的,只能坏没有画的墙结果为n/2 向上取整,求取总和最大值 代码 T int(inp…

一台GTX1080显卡的怪兽,我可不能错过这个机会!

标题:我花了30块钱买了一台电脑主机。 这个配置能赚钱吗? 1. 收购惊喜 那是一个阳光明媚的下午,我在水管修理店里闲逛。 突然,一位老顾客手里拿着一台旧电脑主机匆匆走了进来。 他说:“小王,你能帮我看看…

【Kimi帮我看论文(四)】TransE:Translating Embeddings for Modeling Multi-relational Data

一、论文信息 1 标题 Translating Embeddings for Modeling Multi-relational Data 2 作者 Antoine Bordes, Nicolas Usunier, Alberto Garcia-Durn, Jason Weston, Oksana Yakhnenko 3 研究机构 Universit de Technologie de Compigne – CNRS Heudiasyc UMR 7253 Compi…

绝地求生:PUBG官方公布2024工作计划

大家好,我是闲游盒。 首先今天官方公布了2024工作计划,下面我们一起来了解一下2024工作重点,官方提到的2点:一是通过对PUBG的维护和优化来改善线上服务的质量,二是为玩家们提供更加多姿多彩的游戏体验。我个人看完了全…