C语言sizeof操作符与strlen函数

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的作用,知道数组名不同场景下所表示的含义这种题目就很简单啦!!!


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker 运行异构镜像

概述 关于docker镜像在不同的cpu架构下运行报错的解决办法,作者踩坑验证,在此分享经验 某次工作遇到需要银行内部部署docker镜像,由于行内已经开始走信创的路线,使用鲲鹏系统,arm架构,结果就遇到了standa…

【gpt实践】同时让chatgpt和claude开发俄罗斯方块

最近chatgpt和claude都在使用,其实大部分日常使用场景表现都没有相差太多,想搞一个有趣的小实验,如果同时让chatgpt和claude开发俄罗斯方块谁会表现的更好呢,说干就干! prompt 我选择了用英文描述,毕竟英…

导入空管基础数据

1、首先将data.tar.gz解压到自定义目录中 注意:由于数据文件的压缩包比较大,解压过程可能会持续3~5分钟,请耐心等待。 [rootnode3 ~]# cd /opt/software/ [rootnode3 software]# tar -xzf data.tar.gz -C /opt/ 2、利用SQLyog或者其他数据库…

LeetCode:链表相交

题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 示例 解题思想 将两个链表从尾部对齐,然后进行寻找。 此时我们就可以比较curA和curB是否相同&#xff0c…

Pytorch基础(21)-- torch.repeat_interleave()方法

分享一下自己目前在维护的Github项目,由于本人博士阶段接触了一个全新的研究方向-----使用机器学习、强化学习、深度学习等方法解决组合优化问题,维护这个项目的目的: (1)记录自己阅读过的paper,同时分享一…

G. Rudolf and Subway

解题思路 每条边的边权可选,由颜色决定同一颜色的线路可以直达颜色最多有种考虑将颜色视作链接点,进行分层图跑最短路最终结果除2最多建条边(直接存状态Map跑最短路被毙掉了) import java.io.*; import java.math.BigInteger; im…

【Python】新手入门学习:详细介绍接口分隔原则(ISP)及其作用、代码示例

【Python】新手入门学习:详细介绍接口分隔原则(ISP)及其作用、代码示例 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、Py…

Postman请求API接口测试步骤和说明

Postman请求API接口测试步骤 本文测试的接口是国内数智客(www.shuzike.com)的API接口手机三要素验证,验证个人的姓名,身份证号码,手机号码是否一致。 1、设置接口的Headers参数。 Content-Type:applicati…

三防手机与普通手机的区别在哪里?

一、三防手机和普通手机主要的区别在于其防护性能,它们是针对不同环境和使用场景设计的。三防手机一般包括防水、防尘和防摔三个方面的特点,而普通手机则往往没有这些特点。 防水性能。三防手机的防水性能通常比普通手机更强大。三防手机可以在一定程度上…

【XR806开发板试用】简单移植coremark并测试实际跑分

前言 首先,拿到板子的时候,由于xr806它是个IOT的片子,所以自然而然必然,在预想里就会有很多大佬会把文章出发点考虑在wifi/bt,各种物联网/WEB应用上。那么怎么另辟蹊径回避这个热点又体现出XR806的特色呢,…

一款好用的AI工具——边界AICHAT(三)

目录 3.23、文档生成PPT演示3.24、AI文档翻译3.25、AI翻译3.26、论文模式3.27、文章批改3.28、文章纠正3.29、写作助手3.30、文言文翻译3.31、日报周报月报生成器3.32、OCR-DOC办公文档识别3.33、AI真人语音合成3.34、录音音频总结3.35、域方模型市场3.36、模型创建3.37、社区交…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的条形码二维码检测系统(深度学习+UI界面+训练数据集+Python代码)

摘要:在物流和制造业中,开发一套高效的条形码与二维码识别系统显得尤为关键。本博文深入探讨了如何利用深度学习技术打造出一套先进的条形码及二维码检测系统,并且提供了一套完整的实施方案。该系统搭载了性能卓越的YOLOv8算法,并…

[LeetCode][LCR 175]计算二叉树的深度

题目 计算二叉树的深度 某公司架构以二叉树形式记录,请返回该公司的层级数。 示例 1: 输入:root [1, 2, 2, 3, null, null, 5, 4, null, null, 4] 输出:4 解释: 上面示例中的二叉树的最大深度是 4,沿…

【BI-Dataease】dataease设计思路

参考:https://juejin.cn/post/7089310768671227940 1、BI可视化工具的关键问题是什么? (1)各种数据源的数据结构和类型如何统一? (2)各种图表的配置属性不一致,属性如何绑定到数据…

【C++庖丁解牛】实现string容器的增删查改 | string容器的基本接口使用

🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 前言📖push_b…

关于stm32(CubeMX+HAL库)的掉电检测以及flash读写

1.掉电检测 CubeMX配置 只需使能PVD中断即可 但是使能了PVD中断后还需要自行配置一些PWR寄存器中的参数,我也通过HAL库进行编写 void PVD_config(void) {//配置PWRPWR_PVDTypeDef sConfigPVD; sConfigPVD.PVDLevel PWR_PVDLEVEL_7; …

蓝桥杯2023年第十四届省赛真题-与或异或

一共10个电门&#xff0c;穷举310次 #include<stdio.h> #include<math.h> int main(){int a[5][5], max (int)pow(3, 10), t, op, count 0;a[0][0] a[0][2] a[0][4] 1;a[0][1] a[0][3] 0;for(int k 0; k < max; k){t k;for(int i 1; i < 5; i){fo…

vite ssr服务端渲染

阅读 Vue文档 这一章里有说过&#xff0c;vue是支持服务端渲染的。 通过createSSRApp创建vue组件实例&#xff0c;并使用renderToString将在服务器渲染好template并返回字符串结构&#xff0c;通过替换占位字符将渲染好的字符串输出到html上&#xff0c;这样的一个过程就实现了…

发送短信验证码

​​​​​​【短信验证码-快速报备签名】三网短信接口-短信-短信验证码-短信服务-三网短信接口-短信-三网短信【最新版】_商业智能_电商_金融-云市场-阿里云阿里云云市场提供 专注企业短信服务10年运营与技术积累&#xff0c;稳定、安全、快速。服务&#xff0c;建站服务&…

【word技巧】word文件如何设置打开密码?可以试试这两种方法!

Word文件想要设置密码打开文件&#xff0c;我们可以给文件设置一个打开密码&#xff0c;这样只有知道密码的人才能够打开查看文件&#xff0c;今天分享两个word文件设置打开密码的方法。 一、 打开word文档后&#xff0c;点击【文件】-【信息】-【保护文档】这里有很多选项&a…