sizeof与strlen练习
前言

本篇仅仅是为了更加了解sizeof操作符和strlen函数练习.
对于多条sizeof操作符和strlen函数出现,可能很容易造成头脑不清晰,做题时容易混乱.
目录
- 前言
- 一维数组
- 字符数组
- 情况1:
- 情况2
- 情况3
- 二维数组
练习之前请牢记下面这段话.这将是头脑清晰地关键.
提示:
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表示首元素的地址。
sizeof只关心()里面的类型,并不关心里面放的是什么,这点希望做题目时可以牢记.
strlen()括号里面的是地址,它只会通过访问括号里面的地址,往后一直寻找’\0’,直到’\0’才会停止.
一维数组
#include <stdio.h>
int main()
{int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a)); //1printf("%d\n", sizeof(a + 0)); //2printf("%d\n", sizeof(*a)); //3printf("%d\n", sizeof(a + 1)); //4printf("%d\n", sizeof(a[1])); //5printf("%d\n", sizeof(&a)); //6printf("%d\n", sizeof(*&a)); //7printf("%d\n", sizeof(&a + 1)); //8printf("%d\n", sizeof(&a[0])); //9printf("%d\n", sizeof(&a[0] + 1)); //10return 0;
}

运行结果:
1 -> 16
2 -> 8
3 -> 4
4 -> 8
5 -> 4
6 -> 8
7 -> 16
8 -> 8
9 -> 8
10 -> 8
详细分析答案:
1. 16字节: 数组名a单独出现在sizeof()的括号中表示计算整个数组的大小,即4*4=16字节
2. 4/8字节: a数组名不是单独出现,+0表示首地址表示表示首元素地址,地址的大小4/8字节
3. 4字节: (*a)解引用得到的是数组首元素数组首元素是1,类型为整形,整形大小是4字节.
4. 4/8字节: a+1表示数组第二个元素的地址.地址大小4/8字节.
5. 4字节: a[1]表示数组的第二个元素,元素2的类型是整形,整形的大小是4字节.
6. 4/8字节: &a表示是整个数组的地址,类型为int(*)[4].但是数组的地址也是地址,地址就是4/8字节.
7. 16字节 *&a表示对&a解引用,得到的是整个数组的地址.也可以理解为*和&符号是可以抵消的,即等价于sizeof(a);结果为4*4=16字节
8. 4/8个字节: &a+1表示指向数组最后一个元素的后面.因为&a的类型是int(*)[4],+1会跳过四个整形.
地址的大小就是4/8个字节.
9. 4/8字节: &a[0]表示首元素的地址,地址大小为4/8字节.
10. 4/8字节: (&a[0] + 1表示第二个元素的地址.4/8字节.

字符数组
情况1:
字符数组:
char arr[] = { ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’ };
#include <stdio.h>
#include <string.h>
int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr)); //1printf("%d\n", sizeof(arr + 0)); //2printf("%d\n", sizeof(*arr)); //3printf("%d\n", sizeof(arr[1])); //4printf("%d\n", sizeof(&arr)); //5printf("%d\n", sizeof(&arr + 1)); //6printf("%d\n", sizeof(&arr[0] + 1)); //7printf("%d\n", strlen(arr)); //8printf("%d\n", strlen(arr + 0)); //9printf("%d\n", strlen(*arr)); //10printf("%d\n", strlen(arr[1])); //11printf("%d\n", strlen(&arr)); //12printf("%d\n", strlen(&arr + 1)); //13printf("%d\n", strlen(&arr[0] + 1)); //14return 0;
}

答案分析:
1. 6字节: 表示整个数组的地址,1*6=6个字节
2. 4/8字节 : 首元素地址是4/8个字节.
3. 1字节: *arr表示首元素是一个字符型,1个字节.
4. 1字节: arr[1]表示数组的第二个元素,大小为1个字节.
5. 4/8个字节: &arr表示整个数组的地址,占4/8个字节.
6. 4/8个字节: &arr+1表示数组最后一个元素的后一个位置的地址.4/8个字节
7. 4/8个字节: 表示第二个元素的地址.4/8个字节
strlen函数从参数处开始,遇到’\0’才会停止.
8.随机值.: 由于该数组没有’\0’,所以会向后一直找直到碰到'\0',
9.随机值: arr+0同样表示从数组的第一个元素,从第一个元素往后找,与上面一个道理.
10.报错: strlen()括号里面是地址,所以会访问地址名为a的地址,a的ASCII码值是’97’,访问地址’97’,系统会报错
11.报错: 同理,访问数组第二个元素,地址名b的地址,系统报错
12.随机值: &arr取出的是整个数组的地址,地址还是从数组首地址开始往后找'\0'.
13.随机值: &arr的类型是char(*)[6],+1会跳过这个数组从数组后面开始找'\0'.
14.随机值: 从数组的第二个元素开始找'\0'.
情况2
字符数组:
char arr[] = “abcdef”;
#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "abcdef";printf("%d\n", sizeof(arr)); //1printf("%d\n", sizeof(arr + 0)); //2printf("%d\n", sizeof(*arr)); //3printf("%d\n", sizeof(arr[1])); //4printf("%d\n", sizeof(&arr)); //5printf("%d\n", sizeof(&arr + 1)); //6printf("%d\n", sizeof(&arr[0] + 1)); //7printf("%d\n", strlen(arr)); //8printf("%d\n", strlen(arr + 0)); //9printf("%d\n", strlen(*arr)); //10printf("%d\n", strlen(arr[1])); //11printf("%d\n", strlen(&arr)); //12printf("%d\n", strlen(&arr + 1)); //13printf("%d\n", strlen(&arr[0] + 1)); //14return 0;
}
答案分析:
1. 7字节: 表示整个数组的地址,1*7=7个字节
2. 4/8字节: 首元素地址是4/8个字节.
3. 1字节: *arr表示首元素是,一个字符型,1个字节.
4. 1字节: arr[1]表示数组的第二个元素,大小为1个字节.
5. 4/8个字节: &arr表示整个数组的地址,占4/8个字节.
6. 4/8个字节: &arr+1表示数组最后一个元素的后一个位置的地址4/8个字节
7. 4/8个字节: 表示第二个元素的地址4/8个字节
8. 6字节: 从数组首元素开始,直到最后一个元素’\0’,共6个元素.6*1=6字节.
9. 6字节: arr+0同样表示从数组的第一个元素,从第一个元素往后找,与上面一个道理.
10. 报错: strlen()括号里面是地址,所以会访问地址名为a的地址,a的ASCII码值是’97’,访问地址’97’,系统会报错
11. 报错: 同理,访问数组第二个元素,地址名b的地址,系统报错
12. 6字节: &arr取出的是整个数组的地址,地址还是从数组首地址开始往后找'\0’.
13. 随机值: &arr的类型是char(*)[6],+1会跳过这个数组,从数组后面开始找'\0’.
14. 5字节: 从数组的第二个元素'b'开始往后找'\0'.
情况3
char* p = “abcdef”;
#include <stdio.h>
#include <string.h>
int main()
{char* p = "abcdef";printf("%d\n", sizeof(p)); //1printf("%d\n", sizeof(p + 1)); //2printf("%d\n", sizeof(*p)); //3printf("%d\n", sizeof(p[0])); //4printf("%d\n", sizeof(&p)); //5printf("%d\n", sizeof(&p + 1)); //6printf("%d\n", sizeof(&p[0] + 1)); //7printf("%d\n", strlen(p)); //8printf("%d\n", strlen(p + 1)); //9printf("%d\n", strlen(*p)); //10printf("%d\n", strlen(p[0])); //11printf("%d\n", strlen(&p)); //12printf("%d\n", strlen(&p + 1)); //13printf("%d\n", strlen(&p[0] + 1)); //14return 0;
}
答案分析:

1. 4/8字节: p是一个指针变量,这里指向的是常量字符串,首元素’a’,指针大小4/8字节.
2. 4/8字节: p+1表示指向第二个元素’b’,地址(指针)的大小为4/8字节.
3. 1字节: *p表示首元素’a’,字符a是char类型,占一个字节.
4. 1字节: p[0]同样是表示数组首元素,占一个字节.
5. 4/8个字节: &p表示一级指针变量p的地址,类型为char**的二级指针,指针大小为4/8字节.
6. 4/8个字节: 二级指针&p+1,表示该二级指针的后一个地址,请看图.指针大小4/8字节.
7. 4/8个字节: 表示首元素地址+1,即第二个元素地址,4/8个字节.
8 6字节 从字符串首元素开始,直到最后一个元素’\0’,共6个元素.6*1=6字节.
9 5字节 从字符串第二个元素往后,找’\0’,’bcdef’共5个元素
10. 报错: 表示从a地址,’97’地址往后找’\0’,系统报错.
11. 报错: 同理, 也是访问地址名为’97’的地址.系统报错.
12. 随机值 &p表示一级指针变量p的地址,从存放指针’p’的地址往后找’\0’.
13. 随机值: &p+1表示从存放指针变量’p’的地址后面一个地址,找’\0’.
14 5字节: 从字符串的第二个元素开始找'\0'.
二维数组
//二维数组
#include <stdio.h>
int main()
{int a[3][4] = { 0 };printf("%d\n", sizeof(a)); //1printf("%d\n", sizeof(a[0][0])); //2printf("%d\n", sizeof(a[0])); //3printf("%d\n", sizeof(a[0] + 1)); //4printf("%d\n", sizeof(*(a[0] + 1))); //5printf("%d\n", sizeof(a + 1)); //6printf("%d\n", sizeof(*(a + 1))); //7printf("%d\n", sizeof(&a[0] + 1)); //8printf("%d\n", sizeof(*(&a[0] + 1))); //9printf("%d\n", sizeof(*a)); //10printf("%d\n", sizeof(a[3])); //11return 0;
}
答案:

1. 48字节 a单独出现在sizeof括号中,表示计算整个数组的地址,数组每个元素是整形,4*3*4=48字节
2. 4字节 a[0][0]计算数组首元素的地址,是一个整形占四个字节.
3. 16字节 a[0]是第一行的数组名,数组名单独放在sizeof中,表示第一行的地址,4*4=16字节
4. 4/8字节 a[0]不是单独出现,也没有&(取地址),表示的是第一行第一个元素即a[0][0],后面+1表示第一行第二个元素的地址.
5. 4字节 因为a[0]+1表示第一行第二个元素的地址,则解引用得到的是第一行第二个元素.该元素是整形.
6. 4/8字节 a是数组名,表示二维数组的第一行,a的类型是int(*)[4],那么+1会跳过一行,即表示第二行的地址,地址4/.8字节.
7. 16字节 *(a+1)等价于a[0],第二行的数组名单独放在sizeof里面,表示得到第二行所有元素.
8. 4/8字节 (&a[0] + 1)),&a[0]表示第一行的地址,+1表示第二行的地址,地址是4/8字节
9. 16字节 对第二行解引用,等价于a[1],数组名单独放进sizeof,表示这一行的大小.
10. 16字节 a是表示第一行的地址,*a等价于a[0],类型是int(*)[4].
11. 16字节 a[3]虽然表示第四行数组名,二维数组只有3行,但是sizeof并没有访问第四行,而是计算第四行类型大小,int(*)[4].
希望通过这些练习能更加清楚的指针,通过sizeof和strlen函数里面的参数,指针的来回变化会加深对指针的理解.
相关文章:
sizeof与strlen练习
前言 本篇仅仅是为了更加了解sizeof操作符和strlen函数练习. 对于多条sizeof操作符和strlen函数出现,可能很容易造成头脑不清晰,做题时容易混乱. 目录前言一维数组字符数组情况1:情况2情况3二维数组练习之前请牢记下面这段话.这将是头脑清晰地关键. 提示: sizeof(数组名)&#…...
知识图谱的介绍
知识图谱的由来 谷歌在2012年提出了知识图谱的概念,当时目的在于优化搜索引擎的返回结构,为用户提供更精确的结果。 知识图谱的定义 为了理解知识图谱,我们首先要明白信息与知识的概念。首先,信息表示的是外部的客观事实&#…...
【Redis】Redis高级客户端Lettuce详解
文章目录前提Lettuce简介连接Redis定制的连接URI语法基本使用API同步API异步API反应式API发布和订阅事务和批量命令执行Lua脚本执行高可用和分片普通主从模式哨兵模式集群模式动态命令和自定义命令高阶特性配置客户端资源使用连接池几个常见的渐进式删除例子在SpringBoot中使用…...
Qt——自定义界面之QStyle
1. Qt控件结构简介 首先我们要来讲讲GUI控件结构,这里以QComboBox为例: 一个完整的控件由一种或多种GUI元素构成: Complex Control Element。Primitive Element。Control Element。 1.1 Complex Control Element Complex control elements …...
指针和数组面试题(逐题分析,完善你可能遗漏的知识)
人生不是一种享乐,而是一桩十分沉重的工作。 —— 列夫托尔斯泰 前言:之前我们就学习了数组和指针的知识。 数组:数组就是能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型。 指针:…...
centos7搭建nfs挂载日志目录完整步骤
NFS服务器配置 1.安装NFS服务 首先使用yum安装nfs服务: yum -y install rpcbind nfs-utils 2.创建共享目录 在服务器上创建共享目录,并设置权限。 mkdir /data/share/ chmod 755 -R /data/share/ 3.配置NFS nfs的配置文件是 /etc/exports &…...
三、JavaScript
目录 一、JavaScript和html代码的结合方式 二、javascript和java的区别 1、变量 2、运算 3、数组(重点) 4、函数 5、重载 6、隐形参数arguments 7、js中的自定义对象 三、js中的事件 四、DOM模型 五、正则表达式 一、JavaScript和html代码的结合方…...
深圳大学计软《面向对象的程序设计》实验11 多继承
A. 在职研究生(多重继承) 题目描述 1、建立如下的类继承结构: 1)定义一个人员类CPeople,其属性(保护类型)有:姓名、性别、年龄; 2)从CPeople类派生出学生类CStudent,…...
并发变成实战-原子变量与非阻塞同步机制
文章目录1.锁的劣势2.硬件对并发的支持2.1 比较并交换2.2 非阻塞的计数器3.原子变量类3.1 原子变量是一种“更好的volatile”3.2 性能比较:锁与原子变量4.非阻塞算法4.1 非阻塞的栈4.2 非阻塞的链表4.3 ABA问题非阻塞算法设计和实现上要复杂的多,但在可伸…...
sql数据库常用操作指令
一、操作库-- 创建库create database db1;-- 创建库是否存在,不存在则创建create database if not exists db1;-- 查看所有数据库show databases;-- 查看某个数据库的定义信息 show create database db1; -- 修改数据库字符信息alter database db1 character set ut…...
4-1 定时任务的示例10个
文章目录前言基本命令与格式示例前言 Linux crontab 是用来定期执行程序的命令。当安装完成操作系统之后,默认都已经安装,并启动此任务调度命令。 crond 命令每分钟会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。 基…...
外贸建站多少钱才能达到预期效果?
外贸建站多少钱才能达到预期效果?这是每个外贸企业都会问的问题。作为一个做外贸建站多年的人,我有一些个人的操盘感想。 首先,我认为外贸建站的投资是非常必要的。 因为在现代社会,网站已经成为外贸企业开展业务的必要工具之一…...
【Java学习笔记】5.Java 基本数据类型
Java 基本数据类型 变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。 因此,通过定义不同类型的变量…...
InnoDB 死锁和问题排查
文章目录死锁(dead lock)示例 1问题排查查看连接的线程查看相关的表查看最近一次的死锁信息查看服务器的锁信息查看正在使用的表如何尽可能地避免死锁死锁(dead lock) 两个及以上的事务各自持有对方需要的锁,导致双方…...
tensorflow07——使用tf.keras搭建神经网络(Sequential顺序神经网络)——六步法——鸢尾花数据集分类
使用tf.keras搭建顺序神经网络 六步法——鸢尾花数据集分类 01 导入相关包 02 导入数据集,打乱顺序 03 建立Sequential模型 04 编译——确定优化器,损失函数,评测指标(用哪一种准确率) 05 训练模型——把各项参入填入…...
关于Java连接Hive,Spark等服务的Kerberos工具类封装
关于Java连接Hive,Spark等服务的Kerberos工具类封装 idea连接服务器的hive等相关服务的kerberos认证注意事项 idea 本地配置,连接服务器;进行kerberos认证,连接hive、HDFS、Spark等服务注意事项: 本地idea连接Hadoo…...
大数据框架之Hadoop:MapReduce(五)Yarn资源调度器
Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.0 引入的集群资源管理系统。用户可以将各种服务框架部署在 YARN 上,由 YARN 进行统一地管理和资源分配。 简言之,Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源&…...
uniapp实现地图点聚合功能
前言 在工作中接到的一个任务,在app端实现如下功能: 地图点聚合地图页面支持tab切换(设备、劳务、人员)支持人员搜索显示分布 但是uniapp原有的map标签不支持点聚合功能(最新的版本支持了点聚合功能)&am…...
经典分类模型回顾2—GoogleNet实现图像分类(matlab版)
GoogleNet是深度学习领域的一种经典的卷积神经网络,其在ImageNet图像分类任务上的表现十分优秀。下面是使用Matlab实现GoogleNet的图像分类示例。 1. 数据准备 在开始之前,需要准备一些图像数据用来训练和测试模型,可以从ImageNet等数据集中…...
Java经典面试题——谈谈 final、finally、finalize 有什么不同?
典型回答 final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展, final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。 finally 则是 Java 保…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
