【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)

请添加图片描述
请添加图片描述

Alt

🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
请添加图片描述

文章目录

  • 一、简单介绍Sizeof和Strlen
    • 1.1 Sizeof
    • 1.2 Strlen函数
    • 1.3 Siezof与Strlen小总结:
  • 二、 关于Sizeof和Strlen面试题
    • 2.1 sizeof题目
    • 2.2 strlen题目
    • 2.3 二维数组

本篇是关于Sizeof和Strlen常考面试题解析,也是指针篇的末尾 ,在此感谢大家的支持!


一、简单介绍Sizeof和Strlen

1.1 Sizeof

Sizeof使用指南:

  • Sizeof属于单目操作符
  • 功能:用于计算任何类型的数据所占内存空间的大小
  • 用途广泛,适用于计算数据类型,变量,数组,指针等大小(函数指针变量是不可以的)
  • 在编译中已经完成了计算,返回值是无符号整形size_t,它的单位是字节
  • 对于变量名和数值不是必须要加括号,而数据类型就是必须要加上括号
  • 只关注数据占用内存空间大小,不在乎数据中内容

1.2 Strlen函数

函数原型:

size_t strlen(const char *len)

Strlen函数使用指南:

  • strlen属于库函数,在头文件string.h声明
  • strlen在编译过程中进行计算,局限于字符/字符串的计算中
  • 功能:计算字符串有效长度(结束标志’\0’之前长度)。
  • 在使用strlen的过程中,如果访问了不存在的 索引,可能会出现数据溢出/越界访问的问题。
  • 字符串的初始化,没有对字符串有专门的类型,所以用char类型来初始化
char alen[]="abcd"//字符串数组
char blen[]={'a','b','c','d'};//字符数组

说明】:如果是字符串数组,编译器会自动在结尾补充\0作为结束标志。而对于字符数组,是将字符单个放入数组中,不存在自动补充\0的情况。导致了字符数组中\0的位置是不可知的,通过strlen计算数组大小,需要可能越界访问,找到后面位置\0位置停止。

1.3 Siezof与Strlen小总结:

  • sizeof是操作符 、 strlen是库函数
  • sizeof用于计算任何类型数据的大小、strlen专门计算字符串中的长度
  • sizeof不在乎数据内容、strlen关注字符串结束标志

二、 关于Sizeof和Strlen面试题

温馨提示】:

  • sizeof(数组名):这里面的数组名是整个数组,用于计算整个数组的大小
  • &数组名:这里取出来的是整个数组的地址
  • 二维数组物理逻辑是连续,将一维数组看成二维数组的一个元素,对此二维数组数组名是第一个一维数组的整个地址。

2.1 sizeof题目

通过sizeof函数计算–整型数组

	int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a));--16printf("%d\n", sizeof(a + 0));--4/8printf("%d\n", sizeof(*a));--4printf("%d\n", sizeof(a + 1));--4/8printf("%d\n", sizeof(a[1]));--4printf("%d\n", sizeof(&a));--4/8printf("%d\n", sizeof(*&a));--16printf("%d\n", sizeof(&*a));--4/8printf("%d\n", sizeof(&a + 1));--4/8printf("%d\n", sizeof(&a[0]));--4/8printf("%d\n", sizeof(&a[0] + 1));--4/8

解析】:

  1. sizeof(数组名),用于计算整个数组的大小16
  2. 这里()数组名不是独自的,所以这里a是首元素的地址,+0,没有变化,地址大小就是4/8
  3. 这里()数组名不是独自的,这里a是首元素的地址,*之后就是首元素的数值,大小就是4
  4. 这里()数组名不是独自的,这里a是首元素的地址,+1,就是第二个元素的地址,地址大小就是4/8
  5. 这里就是第二个元素的数值,大小就是4
  6. 这里就是取出了全部数值的地址,地址大小就是4/8
  7. 显示取出整个数组的地址,再解引用得到整个数组的大小16
  8. 这里a就是首元素的地址,*取出的就是首元素的数值,再取地址就是首元素的地址4/8
  9. 先是取出这个全部数组的地址,+1就是跳过整个数组地址,是地址大小4/8
  10. 可以看成&(*(a+0)),这里就是a就是首元素的地址, *取出首元素值,在取地址,还是首元素的地址,地址的大小4/8
  11. 由上面可得到,这里是首元素的地址,+1,就是第二个元素的地址,是地址大小4/8

通过sizeof计算–字符数组

char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));--6printf("%d\n", sizeof(arr + 0));--4/8printf("%d\n", sizeof(*arr));--1printf("%d\n", sizeof(arr[1]));--1printf("%d\n", sizeof(&arr));--4/8printf("%d\n", sizeof(&arr + 1));--4//8printf("%d\n", sizeof(&arr[0] + 1));--4/8

解析】:

  1. 这里代表的是整个数组,用于计算整个数组的大小,6
  2. 这里()数组名不是独自的,这里a是首元素的地址,地址大小就是4/8
  3. 这里()数组名不是独自的,这里a是首元素的地址,就是首元素的数值,1
  4. 这里就是第二个元素的数值,1
  5. 这里就是取出整个数组的地址,是地址大小就是4/8
  6. 这里就是取出整个数组的地址,+1,就是跳过整个数组,是地址大小4/8
  7. 这里就是首元素的地址,+1,就是第二个元素的地址,地址大小就是4/8,&[]可以抵消的呀

通过sizeof计算–字符串数组

	char arr[] = "abcdef";printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr + 0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr + 1));printf("%d\n", sizeof(&arr[0] + 1));

通过sizeof计算–常量字符串

	char *p= "abcdef";printf("%d\n", sizeof(p));--4/8printf("%d\n", sizeof(p + 1));--4/8printf("%d\n", sizeof(*p));--1printf("%d\n", sizeof(p[0]));--1printf("%d\n", sizeof(&p));--4/8printf("%d\n", sizeof(&p + 1));--4/8printf("%d\n", sizeof(&p[0] + 1));--4/8

解析】:

  1. p是一个指针变量,也是存放a的地址,是地址的话大小是4/8
  2. p是第一个字符的地址,+1,就是b的地址,地址大小就是4/8
  3. p是第一个字符的地址,所以得到了字符‘a’, 大小是1
  4. 得到了字符‘a’, 大小是1
  5. &p就是取了p的地址,地址大小就是4/8
  6. 取了p的地址,之后跳过p变量后,得到的地址,是地址大小4/8
  7. 这里的看成 & ( *(p + 0)) + 1, 那么就是b的地址,地址大小就是4/8

2.2 strlen题目

通过strlen函数计算–字符数组

	char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));--随机值printf("%d\n", strlen(arr + 0));--随机值printf("%d\n", strlen(*arr));--err/报错printf("%d\n", strlen(arr[1]));--err/报错printf("%d\n", strlen(&arr));--随机值printf("%d\n", strlen(&arr + 1));--随机值printf("%d\n", strlen(&arr[0] + 1));--随机值

解析】:

  1. 这个是首元素的地址,不知道‘\0’在哪里的,大小就是随机值
  2. 这个是首元素的地址,不知道‘\0’在哪里的,大小就是随机值
  3. 这里取出的是字符‘a’, 不是char* 类型,就是说它不是地址,所以是err
  4. 这里取出的是字符‘b’, 不是char* 类型,就是说它不是地址,所以是err
  5. 整个数组的地址,不知道‘\0’在哪里的,大小就是随机值
  6. 整个数组的地址,+1,跳过整个数组,不知道‘\0’在哪里的,大小就是随机值
  7. 这个是‘b’的地址,不知道‘\0’在哪里的,大小就是随机值

通过strlen函数计算–字符串数组

	char arr[] = "abcdef";printf("%d\n", strlen(arr));--6printf("%d\n", strlen(arr + 0));--6printf("%d\n", strlen(*arr));--err/报错printf("%d\n", strlen(arr[1]));--err/报错printf("%d\n", strlen(&arr));--6printf("%d\n", strlen(&arr + 1));--随机值printf("%d\n", strlen(&arr[0] + 1));--5

解析】:

  1. 首元素的地址,‘f’后面有‘\0’,大小是6
  2. 首元素的地址,‘f’后面有‘\0’,大小是6
  3. 这里取出的是字符‘a’,不是char *类型,就是说它不是地址,所以是err
  4. 这里取出的是字符‘b’,不是char *类型,就是说它不是地址,所以是err
  5. 虽然这个是整个数组的地址,当时地址还是指向a,所以大小是6
  6. 这里跳过了‘f’后面的‘\0’,所以要继续寻找新的‘\0’,大小是随机值
  7. 这里就是‘b’的地址,所以就是大小是5

通过strlen函数计算–常量字符串

	char* p = "abcdef";printf("%d\n", strlen(p));--6printf("%d\n", strlen(p + 1));--5printf("%d\n", strlen(*p));--err/报错printf("%d\n", strlen(p[0]));--err/报错printf("%d\n", strlen(&p));--随机值printf("%d\n", strlen(&p + 1));--随机值printf("%d\n", strlen(&p[0] + 1));--5

解析】:

  1. p是a的地址,大小就是6,遇到\0后停下
  2. p+1就是b的地址,大小就是5
  3. *p得到字符a,err
  4. 这个也是得到了字符a,err
  5. 取出p的地址,要继续寻找新的‘\0’,大小是随机值
  6. 这里是p本身的地址,要继续寻找新的‘\0’,大小是随机值
  7. 先是得到了a的地址,+1,得到b的地址,属于大小是5

2.3 二维数组

	int a[3][4] = { 0 };printf("%d\n", sizeof(a));--48printf("%d\n", sizeof(a[0][0]));--4printf("%d\n", sizeof(a[0]));--16printf("%d\n", sizeof(a[0] + 1));--4/8printf("%d\n", sizeof(*(a[0] + 1)));--4printf("%d\n", sizeof(a + 1));--4/8printf("%d\n", sizeof(*(a + 1)));--16printf("%d\n", sizeof(&a[0] + 1));--4/8printf("%d\n", sizeof(*(&a[0] + 1)));--16printf("%d\n", sizeof(*a));--16printf("%d\n", sizeof(a[3]));--16

解析】:

  1. 代表整个数组,用于计算整个数组的大小48
  2. 就是第一行第一列的元素数值,大小是4
  3. 这个就是二维数组的首元素,就是第一行数组名,计算第一行数组的大小,16
  4. 第一行数组名,但是这个数组名不是单独,就是第一行一个元素的地址,+1,第一行第二个元素的地址,是地址的大小就是4/8
  5. 第一行数组名,就是arr[0][0]的地址,+1,就是arr[0][1]的地址,再解引用就是得到数值,大小就是4
  6. a不是独自的,是二维数组的首元素的地址,就是第一行数组的地址,+1,第二行数组的地址,是地址的大小就是4/8
  7. a不是独自的,是二维数组的首元素的地址,+1,第二行数组的地址,再解引用就是第二行数组的数值,大小就是16
  8. a[0]是第一行数值名,&之后取得第一行数组的地址,+1,就是第二行数组地址,4/8
  9. 这个就是第二行数组,大小就是16
  10. 就是的第一行数组地址,解引用就是,第一行的数组,大小就是16
  11. 就是的第三行数组名,计算第三行的数组的大小,16

请添加图片描述
以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二C语言笔记,希望对你在学习C语言中有所帮助!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊聊 ASP.NET Core 中间件(一):一个简单的中间件例子

前言:什么是中间件 服务器在收到 HTTP 请求后会对用户的请求进行一系列的处理,比如检查请求的身份验证信息、处理请求报文头、检查是否存在对应的服务器端响应缓存、找到和请求对应的控制器类中的操作方法等,当控制器类中的操作方法执行完成…

MLP手写数字识别(3)-使用tf.data.Dataset模块制作模型输入(tensorflow)

1、tensorflow版本查看 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、MNIST数据集下载与预处理 (train_images,train_labels),(test_images,test_labels) tf.keras.datasets.mnist.load_data()…

多线程事务怎么回滚

1、背景介绍 1,最近有一个大数据量插入的操作入库的业务场景,需要先做一些其他修改操作,然后在执行插入操作,由于插入数据可能会很多,用到多线程去拆分数据并行处理来提高响应时间,如果有一个线程执行失败…

深度学习500问——Chapter08:目标检测(7)

文章目录 8.3.8 RFBNet 8.3.9 M2Det 8.3.8 RFBNet RFBNet有哪些创新点 1. 提出RF block(RFB)模块 RFBNet主要想利用一些技巧使得轻量级模型在速度和精度上达到很好的trade-off的检测器。灵感来自人类视觉的感受野结构Receptive Fields(RFs…

【Mac】mac 安装 prometheus 报错 prometheus: prometheus: cannot execute binary file

1、官网下载 Download | Prometheus 这里下载的是prometheus-2.51.2.linux-amd64.tar.gz 2、现象 解压之后启动Prometheus 启动脚本: nohup ./prometheus --config.fileprometheus.yml > prometheus.out 2>&1 & prometheus.out日志文件&#xff…

WIN10 anaconda 安装 CondaError: Run ‘conda init‘ before ‘conda activate‘

1 下载 https://www.anaconda.com/download/success 2 安装 3 修改环境变量 安装后修改环境变量 4 winrun 进入命令窗口 输入cmd 输入 conda info 5 创建 虚拟环境 conda create -n yolov8 python3.8 -y 6 CondaError: Run ‘conda init’ before ‘conda activate’ c…

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了,要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看,可以看我下面总结的干货,哈哈 第一个问题:stage架构和fa架构的区…

SpringBoot+阿里云实现验证码登录注册及重置密码

开通阿里云短信服务 阿里云官网 创建API的Key 可以使用手机号或者刷脸来进行创建Key 创建成功 开通完成以后接下来实现代码请求阶段 配置maven依赖 <!-- 阿里云 oss 短信 依赖--><dependency><groupId>com.aliyun</groupId><artifactId>dysm…

力扣763. 划分字母区间

Problem: 763. 划分字母区间 文章目录 题目描述思路复杂度Code 题目描述 思路 1.创建一个名为 last 的数组&#xff0c;用于存储每个字母在字符串 s 中最后出现的位置。然后&#xff0c;获取字符串 s 的长度 len。 2.计算每个字母的最后位置&#xff1a;遍历字符串 s&#xff0…

Python梯度提升决策树库之lightgbm使用详解

概要 LightGBM是一个快速、分布式、高性能的梯度提升决策树(Gradient Boosting Decision Tree)库,它在机器学习和数据挖掘领域被广泛应用。本文将介绍LightGBM库的安装方法、主要特性、基本功能、高级功能、以及在实际应用中的场景和总结。 安装 首先,需要安装LightGBM库…

ORACLE 性能优化 高水位调节

当我需要去做优化时,有一个固定的优化思路:SQL优化->索引优化->分区优化->优化器hints优化 SQL 语句优化 1. 选用适合的 ORACLE 优化器 ORACLE 的优化器共有 3 种 : a. RULE ( 基于规则 ) b. COST ( 基于成本 ) c. CHOOSE ( 选 择性) 设置缺省的优化器, 可以通…

基于RK1126的小型化低功耗AI相机,支持人体特征识别、人脸特征识别、案例帽识别等

提供可定制的⼀套 AI相机软硬件开发平台&#xff0c; 硬件采⽤ RockchipRV1126处理器解决 ⽅案&#xff0c;可选择搭配 SonyIMX系列传感器&#xff0c;POE供电与数据传输&#xff0c;采⽤ 38板标准结构设计&#xff0c;快速按需定制外壳&#xff0c;⽀撑从开发到验证到批量⽣产…

【webrtc】MessageHandler 6: 基于线程的消息处理:StunRequest实现包发送和超时重传

G:\CDN\rtcCli\m98\src\p2p\base\stun_request.cc使用OnMessage 实现包的发送和包的超时重传StunRequest 一个StunRequest 代表是一个独立的请求的发送STUN消息 要不是发送前构造好的,要不就是按照需要构建的使用StunRequestManager: 每一个STUNRequest 携带一个交互id 写入m…

【区块链】共识算法简介

共识算法简介 区块链三要素&#xff1a; 去中心化共识算法智能合约 共识算法作为区块链三大核心技术之一&#xff0c;其重要性不言而喻。今天就来简单介绍共识算法的基本知识。 最简单的解释&#xff0c;共识算法就是要让所有节点达成共识&#xff0c;保证少数服从多数&#x…

【docker】maven 打包docker的插件学习

docker-maven-plugin GitHub地址&#xff1a;https://github.com/spotify/docker-maven-plugin 您可以使用此插件创建一个 Docker 映像&#xff0c;其中包含从 Maven 项目构建的工件。例如&#xff0c;Java 服务的构建过程可以输出运行该服务的 Docker 映像。 该插件是 Spot…

【JAVA进阶篇教学】第九篇:MyBatis-Plus用法介绍

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第九篇&#xff1a;MyBatis-Plus用法介绍。 在 MyBatis-Plus 3.5.0 中&#xff0c;LambdaQueryWrapper支持多种条件构造方式&#xff0c;除了等于&#xff08;eq&#xff09;、不等于&#xff08;ne&#xff09;、大于&a…

【游戏行业】2024年电子游戏分类,国内游戏产业报告,发展趋势

文章目录 一、电子游戏分类1、传统游戏分类2、混合手游分类3、二次元、开放设计、调查问卷 二、游戏产业报告1、游戏产业数据2、游戏公司名单&#xff08;独角兽&#xff09;3、营收与利润&#xff08;对比互联网、国企&#xff09; 三、发展趋势1、游戏行业上下游2、游戏行业趋…

SSM整合-前后端分离-项目环境搭建 (上)

整合SSM 项目基础环境搭建项目介绍创建项目项目全局配置web.xmlSpringMVC配置配置Spring和MyBatis, 并完成整合创建表, 使用逆向工程生成Bean, XxxMapper和XxxMapper.xml注意事项和细节说明 实现功能01-搭建Vue前端工程需求分析/图解代码实现搭建Vue前端工程vue3项目目录结构梳…

力扣例题(接雨水)

链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路&#xff1a; 判断一块地方是否可以接到雨水&#xff0c;只需要判断他是否有左右边界使他可以接到水 左右边界分别为此处左侧的最高点和右侧的最高点 同时此处可接雨水的高度为左右两…

VMware虚拟机安装Linux(CentOS)【超详细】

参考大佬文章&#xff1a;VMware虚拟机安装Linux教程(超详细)_vmware安装linux虚拟机-CSDN博客 目录 一、获取映射文件 二、新建虚拟机 三、安装操作系统 四、切换系统用户 一、获取映射文件 参考大佬文章获取映射文件&#xff0c;以及对应修改后缀名的方法 二、新建虚拟…