浅学指针(5)sizeof和strlen的进阶理解

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 1. sizeof和strlen的对⽐
    • 1.1 sizeof
    • sizeof不是函数,是运算符
  • 1.2 strlen
    • 1.3 sizeof 和 strlen的对⽐
  • 2. 数组和指针笔试题解析
    • • sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节 • &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的) 除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。
    • 2.1 ⼀维数组
    • 2.2 字符数组
    • 代码4: 这里有重要内容
    • strlen计算内容是地址时,计算的是地址的内容
  • 2.3 ⼆维数组
  • 3. 指针运算笔试题解析
    • 3.2 题⽬2
    • #的作用打印Ox前缀
    • 3.3 题⽬3
    • 3.4 题⽬4
    • 3.5 题⽬5
    • 做这种题最好画图
    • 3.6 题⽬6
    • 3.7 题⽬7


前言

目的:深入学习sizeof和strlen和有关2维数组的指针形式

1. sizeof和strlen的对⽐

1.1 sizeof

在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。
⽐如:

sizeof不是函数,是运算符

#inculde <stdio.h>
int main()
{int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);//也可以这样printf("%d\n", sizeof(int));return 0;
}

输出结果都是一样的,都是4,

1.2 strlen

strlen 是C语⾔库函数,功能是求字符串⻓度。函数原型如下:

	size_t strlen ( const char * str );

统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找。

#include <stdio.h>
int main()
{char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";printf("%d\n", strlen(arr1));//1printf("%d\n", strlen(arr2));//2printf("%d\n", sizeof(arr1));//3printf("%d\n", sizeof(arr1));//4return 0;
}

代码1:随机值,没有\0; 代码2:结果是3
代码3:结果3 代码4:结果是4

1.3 sizeof 和 strlen的对⽐

(1)sizeof

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

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

后面所有题都是在下面基础上:

• sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,
单位是字节
• &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素
的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。

2.1 ⼀维数组

写出所占字节数

	int a[] = {1,2,3,4};printf("%d\n",sizeof(a));//单单数组名,是整个数组,16printf("%d\n",sizeof(a+0));//首元素地址加0,为地址4/8个字节printf("%d\n",sizeof(*a));//为首元素内容,4printf("%d\n",sizeof(a+1));//首元素地址加1,为第2个元素地址 ,4/8printf("%d\n",sizeof(a[1]));//4printf("%d\n",sizeof(&a));//地址 4/8printf("%d\n",sizeof(*&a));//所有元素地址,解引用为所有元素内容,4*4=16printf("%d\n",sizeof(&a+1));//地址,4/8printf("%d\n",sizeof(&a[0]));//地址4/8printf("%d\n",sizeof(&a[0]+1));//首元素地址加1,第2个元素地址,4/8

2.2 字符数组

代码1:

	char arr[] = {'a','b','c','d','e','f'};printf("%d\n", sizeof(arr));//计算的是整个数组大小,6个字节printf("%d\n", sizeof(arr+0));//arr+0是数组第一个元素的地址4/8printf("%d\n", sizeof(*arr));//*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

代码2:

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

代码3:

	char arr[] = "abcdef";printf("%d\n", sizeof(arr));//7printf("%d\n", sizeof(arr+0));//arr+0是数组首元素的地址,地址的大小4/8printf("%d\n", sizeof(*arr));//*arr是数组首元素地址,1printf("%d\n", sizeof(arr[1]));//1printf("%d\n", sizeof(&arr));//整个数组地址,数组地址也是地址4/8printf("%d\n", sizeof(&arr+1));//&arr+1跳过整个数组,指向了数组的后,4/8printf("%d\n", sizeof(&arr[0]+1));//&arr[0]+1是第2个元素地址4/8

代码4:
这里有重要内容

	char arr[] = "abcdef";printf("%d\n", strlen(arr));//6printf("%d\n", strlen(arr+0));//arr+0是首元素地址,6printf("%d\n", strlen(*arr));//err(错误)printf("%d\n", strlen(arr[1]));//err'b'没有\0printf("%d\n", strlen(&arr));//————&arr虽然是数组地址,但是也是指向数组起始位置printf("%d\n", strlen(&arr+1));//随机值printf("%d\n", strlen(&arr[0]+1));//&arr+1是第2个元素的地址

strlen计算内容是地址时,计算的是地址的内容

代码5:

	char *p = "abcdef";printf("%d\n", sizeof(p));//p是指针变量,是地址4/8printf("%d\n", sizeof(p+1));//p+1是'b' 的地址,4/8printf("%d\n", sizeof(*p));//*p计算'a'大小1个字节printf("%d\n", sizeof(p[0]));//p[0] = *(p+0) 1个字节printf("%d\n", sizeof(&p));//&p是地址,这里相当于2级指针4/8printf("%d\n", sizeof(&p+1));//&p+1是指向p指针变量后面的空间,也是地址,是4/8字节printf("%d\n", sizeof(&p[0]+1));//&p[0]+1是'b'的地址,是地址就是4/8个字节

代码6:

	char *p = "abcdef";printf("%d\n", strlen(p));//6printf("%d\n", strlen(p+1));//跳过1个字节,计算后面的为5printf("%d\n", strlen(*p));//errprintf("%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

2.3 ⼆维数组

	int a[3][4] = {0};printf("%d\n",sizeof(a));//4*12=48printf("%d\n",sizeof(a[0][0]));//4printf("%d\n",sizeof(a[0]));//a[0]是第一行这个一维数组的数组名,数组名单独放在sizeof了,计算的是第一行大小,单位是字节,16printf("%d\n",sizeof(a[0]+1));//a[]第一行这个一维数组的数组名,这里表示数组首元素,也就是a[0][0]的地址,a[0] + 1是a[0][1]的地址printf("%d\n",sizeof(*(a[0]+1));//a[0][1] - 4个字节printf("%d\n",sizeof(a+1));//a是二维数组的数组名,但是没有&,也没有单独放在sizeof内部,所以这里的a是数组收元素的地址,应该是第一行的地址,a+1是第二行的地址printf("%d\n",sizeof(*(a+1)));//*(a + 1) ==> a[1] - 第二行的数组名,单独放在sizeof内部,计算的是第二行的大小,为16printf("%d\n",sizeof(&a[0]+1));//&a[0]是第一行的地址,&a[0]+1就是第二行的地址,4/8printf("%d\n",sizeof(*(&a[0]+1)));//访问的是第二行,计算的是第二行的大小,16个字节,相当于放在int(*p)[4] = &a[o] + 1;printf("%d\n",sizeof(*a));//这里的a是第一行的地址,*a就是第一行,sizeof(*a)计算的是第一行的大小-16printf("%d\n",sizeof(a[3]));//这里不存在越界,因为sizeof内部的表达式不会真实计算的,计算的是第四行的类型大小-16

数组名的意义:

  1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
  2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表⽰⾸元素的地址。

3. 指针运算笔试题解析

3.1 题⽬1:

#include <stdio.h>
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的结果是什么?

在这里插入图片描述
*(ptr-1)解析:
在这里插入图片描述

3.2 题⽬2

指针+整数

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%p\n", p + 0x1);//0x100000+20 == x100014printf("%p\n", (unsigned long)p + 0x1);//0x100000+1 == 0x100001printf("%p\n", (unsigned int*)p + 0x1);//0x100000+1 == 0x100004return 0;
}

结果:
在这里插入图片描述
也可以以16进制打印:

struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%#x\n", p + 0x1);//0x100000+20 == x100014printf("%#x\n", (unsigned long)p + 0x1);//0x100000+1 == 0x100001printf("%#x\n", (unsigned int*)p + 0x1);//0x100000+1 == 0x100004return 0;
}

#的作用打印Ox前缀

结果:
在这里插入图片描述

3.3 题⽬3

重点看

#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };//这里是(),是逗号表达式,不是{},逗号表达式结果是运算到最右边的结果//int a[3][2] = { 1, 3, 5 };int *p;p = a[0];printf( "%d", p[0]);return 0;
}

分析:
在这里插入图片描述
输出结果:
在这里插入图片描述
为什么是1,其实是把a[0](数组第一行)给p,其实给的是第一行首元素地址。

3.4 题⽬4

//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
int main()
{int a[5][5];int(*p)[4];p = a;printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//-4,-4(元素个数)return 0;
}

分析:
在这里插入图片描述
在这里插入图片描述
输出结果:
在这里插入图片描述

3.5 题⽬5

#include <stdio.h>
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&aa + 1);//跳过一个数组int *ptr2 = (int *)(*(aa + 1));//相当于a[1],第2行,ptr得到的是第2行首元素地址printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

做这种题最好画图

在这里插入图片描述

输出结果:
在这里插入图片描述

3.6 题⽬6

#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};//指针数组char**pa = a;pa++;printf("%s\n", *pa);return 0;
}

分析:

在这里插入图片描述

输出结果:
在这里插入图片描述

3.7 题⽬7

#include <stdio.h>
int main()
{char *c[] = {"ENTER","NEW","POINT","FIRST"};char**cp[] = {c+3,c+2,c+1,c};char***cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *--*++cpp+3);printf("%s\n", *cpp[-2]+3);printf("%s\n", cpp[-1][-1]+1);return 0;
}

分析:
解引用cpp是找到cp[ ]里面的内容如:c + 3
在这里插入图片描述
在这里插入图片描述
输出结果:
在这里插入图片描述
好了,指针的学习就到这里就结束了,都看到这里了,点一个赞,谢谢。

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

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

相关文章

51单片机应用从零开始(九)·数组

目录 1. 用字符型数组控制 P0 口 8 位 LED 流水点亮 2. 用 P0 口显示字符串常量 1. 用字符型数组控制 P0 口 8 位 LED 流水点亮 C语言中的字符型数组是一种数据类型&#xff0c;它是一个由字符组成的序列&#xff0c;以空字符\0结尾。在声明字符型数组时&#xff0c;需要指…

Git【成神路】

目录 1.为啥要学git啊&#xff1f;&#x1f615;&#x1f615;&#x1f615; 2.版本控制软件的基本功能 &#x1f91e;&#x1f91e;&#x1f91e; 3.集中式版本控制 &#x1f936;&#x1f936;&#x1f936; 4.分布式版本控制&#x1f60e;&#x1f60e;&#x1f60e; …

一款自动帮你生成UI界面和代码的AI神器

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 只要描述你想要的UI是什么样的&#xff0c;它就能帮你生成&#xff0c;是不是很神奇&#xff1f; v0使用 AI 模型根据简单的文本提示生成用户界面和代码&#xff…

利用STM32内置温度传感器实现温度监测系统

STM32微控制器是一款强大的嵌入式处理器&#xff0c;具有广泛的应用领域。其中&#xff0c;一些STM32微控制器内置了温度传感器&#xff0c;可以方便地实现温度监测功能。本文将详细介绍如何利用STM32内置温度传感器实现温度监测系统&#xff0c;并提供相应的示例代码。 一、硬…

智慧灯杆系统平台架构设计需要考虑的几个要点

智慧灯杆是一种集成了各种先进技术的道路照明设施。它不仅提供照明服务&#xff0c;还可以具有物联网技术、视频监控、环境监测、广播通讯、无线网络覆盖等多种功能。这些智能功能可以通过互联网进行控制和管理&#xff0c;从而实现智慧城市的建设。智慧灯杆能够提升城市的智能…

Wpf 使用 Prism 实战开发Day07

待办事项页面设计 效果图: 一.布局设计 页面主要分上下布局&#xff0c;分2行进行设计&#xff0c;使用 Grid.RowDefinitions 将页面分上下2行 例如&#xff1a; <Grid.RowDefinitions><RowDefinition Height"auto"/><RowDefinition/> </Gri…

创意项目开源,文生图、排序/优选等...,持续开源更新!!

热烈欢迎大家在git上star&#xff01;&#xff01;&#xff01;冲鸭&#xff01;&#xff01;&#xff01; 1.dalle1在厨房家具中文场景上训练。 GitHub - leeguandong/DALLE1: dalle1在中文家具场景的微调&#xff0c;效果并不好dalle1在中文家具场景的微调&#xff0c;效果…

MYSQL报错 [ERROR] InnoDB: Unable to create temporary file; errno: 0

起因 服务器的mysql不支持远程访问&#xff0c;在修改完相关配置后重启服务出错。 2023-12-03T10:12:23.895459Z 0 [Note] C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld.exe (mysqld 5.7.22-log) starting as process 15684 ... 2023-12-03T10:12:23.908886Z 0 [Note…

nodejs基于vue的社区物业缴费报修管理系统7vwc6

运行软件:vscode 前端nodejsvueElementUi 语言 node.js 框架&#xff1a;Express/koa 前端:Vue.js 数据库&#xff1a;mysql 开发软件&#xff1a;VScode/webstorm/hbuiderx均可 数据库用MySQL,后台用vue框架 基本要求&#xff1a; 1. 对项目进行详细实际的需求分析。 2. 在网…

前端面试灵魂提问(1)

1.自我介绍 2.在实习中&#xff0c;你负责那一模块 3.any与unknow的异同 相同点&#xff1a;any和unkonwn 可以接受任何值 不同点&#xff1a;any会丢掉类型限制&#xff0c;可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查&#xff0c;所以在使用一个…

2024年天津财经大学珠江学院专升本专业课报名缴费操作流程

天津财经大学珠江学院专升本专业课报名缴费操作流程 天津财经大学珠江学院专升本专业课报名就是缴费&#xff0c;只需要使用中国银行交专业课报名费即可。 缴费操作流程如下&#xff1a; 登录中国银行手机 APP—点击“生活”—在界面 最左上角选择定位为“天津市”—点击“生…

❀My学习Linux命令小记录(6)❀

目录 ❀My学习Linux命令小记录&#xff08;6&#xff09;❀ 26.ps指令 27.grep指令 28.awk指令 29.sed指令 30.wc指令 ❀My学习Linux命令小记录&#xff08;6&#xff09;❀ 26.ps指令 功能说明&#xff1a;报告当前系统的进程状态。 (ps.ps命令 用于报告当前系统的进…

Jupyter NoteBook未授权访问漏洞

任务一&#xff1a; 复现未授权访问的漏洞 任务二&#xff1a; 利用Jupter Notebook控制台执行系统命令&#xff0c;读取/etc/passwd内容 1.搭建环境 2.new下面直接进入终端&#xff0c;而且也不需要登录&#xff0c;我就直接进入了管理界面 3.直接把指令输入进入&#xf…

【自动化测试教程】Java+Selenium自动化测试环境搭建

本主要介绍以Java为基础&#xff0c;搭建Selenium自动化测试环境&#xff0c;并且实现代码编写的过程。 1.Selenium介绍 Selenium 1.0 包含 core、IDE、RC、grid 四部分&#xff0c;selenium 2.0 则是在两位大牛偶遇相互沟通决定把面向对象结构化&#xff08;OOPP&#xff09…

TCP三次握手与四次挥手

TCP三次握手与四次挥手 TCP三次握手与四次挥手解析 客户端连接服务器&#xff08;三次握手&#xff09;客户端关闭与服务器连接&#xff08;四次挥手&#xff09; 总结 TCP三次握手与四次挥手、流量控制(滑动窗口)、拥塞控制、半连接状态、2MSL TCP三次握手与四次挥手 TCP标…

LongAddr

目录 1. 引言 2. AtomicInteger的局限性 3. AtomicInteger与LongAdder 的性能差异 4.LongAdder 的结构 LongAddr架构 Striped64中重要的属性 Striped64中一些变量或者方法的定义 Cell类 5. 分散热点的原理 具体流程图 6. 在实际项目中的应用 7. 总结 1. 引言 在这一…

抖音外卖商品模型

目录 一、抖音外卖商品模型 二、商家运营流程 &#xff08;一&#xff09;商家入驻流程 &#xff08;二&#xff09;商品发布流程 三、推广带货流程 &#xff08;一&#xff09;短视频带货 &#xff08;二&#xff09;直播视频带货 【直播工具】 【直播流程】 直播前…

Redis--13--缓存一致性问题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 缓存一致性问题1、先更新缓存&#xff0c;再更新DB方案二&#xff1a;先更新DB&#xff0c;再更新缓存方案三&#xff1a;先删缓存&#xff0c;再写数据库推荐1&…

Ubuntu中安装IDEA,并配置桌面快捷方式

1、首先自己下载linux版本的idea 这一步省略不说了 2、在/usr/local/路径下新建安装目录IDEA&#xff1a; mkdir -p /usr/local/IDEA3、执行如下命令&#xff0c;解压下载的压缩包到指定目录&#xff1a; tar -zxvf ideaIU-2022.3.3.tar.gz -C /usr/local/IDEA 注意&#x…

(四)基于高尔夫优化算法GOA求解无人机三维路径规划研究(MATLAB代码)

一、无人机模型简介&#xff1a; 单个无人机三维路径规划问题及其建模_IT猿手的博客-CSDN博客 参考文献&#xff1a; [1]胡观凯,钟建华,李永正,黎万洪.基于IPSO-GA算法的无人机三维路径规划[J].现代电子技术,2023,46(07):115-120 二、高尔夫优化算法GOA简介 高尔夫优化算法…