当前位置: 首页 > news >正文

C语言第二十三弹---指针(七)

 ✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

指针

1、sizeof和strlen的对比

1.1、sizeof

1.2、strlen

1.3、sizeof 和 strlen的对比

2、数组和指针笔试题解析

2.1、⼀维数组

2.2、二维数组

总结


1、sizeof和strlen的对比

1.1、sizeof

在学习操作符的时候,我们学习了 sizeof sizeof 计算变量所占内存空间大小的 单位是
字节 ,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
sizeof 只关注占注内存空间的大小,不在乎内存中存放什么数据。
比如:
#include <stdio.h>
int main()
{int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;
}

  

注:变量可以不加括号,类型必须加圆括号(小括号)。

1.2、strlen

strlen 是C语言库函数,功能是求字符串长度。函数原型如下:
size_t strlen ( const char * str );
注:strlen需要包含头文件#include<string.h>,可以在cplusplus旧版本搜索,前面函数章节有详细讲解查库函数的两个工具。
统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。
strlen 函数会⼀直向后找 \0 字符,直到找到为止,所以 可能存在越界查找。
#include<string.h>
#include <stdio.h>
int main()
{char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr2));return 0;
}
为什么strlen(arr1)是15呢?按照我们正常思维是不是应该为3呢?
听小林娓娓道来,首先需要知道strlen是如何进行计算的,计算的是首地址到'\0'直接的字符个数,arr1数组是通过单引号进行初始化的,初始化几个元素就是几个元素,其中没有包含\0,因此在计算字符串长度时,遇到'\0'才停止,但是此处不知道什么为'\0',所以该长度为随机值(编译器不同答案就可能不一样)。
那有uu会说为什么strlen(arr2)就是3呢?
这就考到我们之前需要字符串时讲的一个知识点,双引号包裹的字符串在末尾会自动加上'\0',因此在计算arr2的长度时,在字符c之后遇到'\0'就会停止,也就能计算正确字符串长度。
为什么sizeof(arr2)是4呢?按照正常思维是不是应该为3呢?
首先我们需要知道sizeof是如何进行计算的,sizeof计算的是占用内存空间的大小,单位为字节,上述我们刚刚讲到双引号包裹的字符串在末尾会自动加上'\0',因此arr2中的元素有abc\0四个,根据数组不加大小的原则,实际为几个字节那么数组就占用几个字节,因此arr2占用的大小为4字节,即sizeof(arr2)为4。

1.3、sizeof 和 strlen的对比

sizeof
strlen
1. sizeof是操作符
2. sizeof计算操作数所占内存的大小, 单位是字节
3. 不关注内存中存放什么数据
1. strlen是库函数,使用需要包含头⽂件 string.h
2. srtlen是求字符串长度的,统计的是 \0 之前字符的个数
3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能会越界

2、数组和指针笔试题解析

2.1、⼀维数组

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

sizeof计算操作数所占内存的大小, 单位是字节

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));

//数组名单独放在sizeif内部代表的是整个数组大小(数据类型大小*数据个数),因此为16字节
printf("%d\n",sizeof(a+0));

//数组名不是单独放在sizeof内部,因此数组名为数组首元素地址,+0还是此地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*a));

//数组名为首元素地址,*a则为数组第一个元素,类型为int,因此为4字节
printf("%d\n",sizeof(a+1));

//数组名不是单独放在sizeof内部,因此数组名为数组首元素地址,+1则向后移动一个int类型大小位置,但还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(a[1]));

//a[1]为数组第二个元素,类型为int,因此为4字节
printf("%d\n",sizeof(&a));

//&a为整个数组的地址,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*&a));

//&a为整个数组的地址,解引用则为整个数组,因此此处为整个数组大小,即16字节

//也可以理解为*和&可以相互抵消,就是数组名单独在sizeof内部
printf("%d\n",sizeof(&a+1));

//&a为整个数组的地址,+1即向后走整个数组大小步,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(&a[0]));

//a[0]为第一个元素,&a[0]为第一个元素的地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(&a[0]+1));

//a[0]为第一个元素,&a[0]为第一个元素的地址,+1则向后走int类型大小步,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

2.2、二维数组

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
sizeof计算操作数所占内存的大小, 单位是字节
int a[3][4] = {0};
printf("%d\n",sizeof(a));
//数组名单独放在sizeof内部代表整个数组大小(数据元素类型大小*元素个数,即4*3*4),因此为48字节。
printf("%d\n",sizeof(a[0][0]));
//a[0][0]为第一行第一列的元素,类型为int,因此大小为4字节。
printf("%d\n",sizeof(a[0]));
//a[0]单独放在sizeof内部代表整行元素,大小为4*4字节
printf("%d\n",sizeof(a[0]+1));
//a[0]为首行第一个元素地址,+1为第二行第一个元素地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(a[0]+1)));
//a[0]为首行第一个元素地址,+1为第二行第一个元素地址,解引用则为第二行首元素,int类型,4字节。
printf("%d\n",sizeof(a+1));
//a为首元素地址,在二维数组中,首元素地址为首行地址,+1则为第二行地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(a+1)));
//a为首元素地址,在二维数组中,首元素地址为首行地址,+1则为第二行地址,解引用则为第二行元素大小,4*4字节。
printf("%d\n",sizeof(&a[0]+1));
//&a[0]为首行的地址,+1位第二行的地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(&a[0]+1)));
//&a[0]为首行的地址,+1位第二行的地址,解引用则为第二行的大小,4*4字节。
printf("%d\n",sizeof(*a));
//a为首元素地址,在二维数组中,首元素地址为首行地址,解引用则为首行的大小,4*4字节。
printf("%d\n",sizeof(a[3]));
//a[3]为第四行的地址,单独放在sizeof内部代表整行元素,虽然越界了,但是sizeof只看类型,大小为4*4字节。

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

相关文章:

  • Android---PermissionX实现动态权限申请
  • vscode开发FPGA(0)--windows平台搭建
  • JS逆向进阶篇【去哪儿旅行登录】【上篇】
  • 意外删除照片数据?恢复照片数据的 10 大照片恢复工具方法
  • 2024/2/12 图的基础知识 2
  • 无人机飞行原理,多旋翼无人机飞行原理详解
  • 【国产MCU】-CH32V307-基本定时器(BCTM)
  • kali系统概述、nmap扫描应用、john破解密码、抓包概述、以太网帧结构、抓包应用、wireshark应用、nginx安全加固、Linux系统加固
  • 【c语言】字符串常见函数 上
  • 【QT+QGIS跨平台编译】之三十:【NetCDF+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
  • linux系统zabbix监控服务端部署
  • 电路设计(16)——纪念馆游客进出自动计数显示器proteus仿真
  • C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(2)折线图显示
  • 深入理解XGBoost:集成学习与堆叠模型
  • 【c语言】字符串常见函数 下
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • emacs初体验
  • es的写入过程
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • MySQL几个简单SQL的优化
  • Redash本地开发环境搭建
  • 从零开始在ubuntu上搭建node开发环境
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 漂亮刷新控件-iOS
  • 如何编写一个可升级的智能合约
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 试着探索高并发下的系统架构面貌
  • 自定义函数
  • Java总结 - String - 这篇请使劲喷我
  • 正则表达式-基础知识Review
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • #if和#ifdef区别
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (3)STL算法之搜索
  • (待修改)PyG安装步骤
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (一一四)第九章编程练习
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • .NET中统一的存储过程调用方法(收藏)
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • .pop ----remove 删除
  • /bin、/sbin、/usr/bin、/usr/sbin
  • @private @protected @public
  • [Android]Android开发入门之HelloWorld
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [bzoj 3124][sdoi 2013 省选] 直径
  • [bzoj4240] 有趣的家庭菜园