指针的深入理解(六)

指针的深入理解(六)

个人主页:大白的编程日记
感谢遇见,我们一起学习进步!


文章目录

  • 指针的深入理解(六)
    • 前言
    • 一. sizeof和strlen
      • 1.1sizeof
      • 1.2strlen
      • 1.3sizeof和strlen对比
    • 二.数组名和指针加减
      • 2.1数组名的理解
      • 2.2指针加减整数
      • 2.3指针的大小
    • 三. 数组和指针笔试题解析
      • 3.1 一维数组
      • 3.2 字符数组
      • 3.3常量字符串
    • 四.二维数组
      • 4.1二维数组的理解
      • 4.2二维数组练习
    • 后言

前言

经过前面的学习我们已经把指针的内容全部学完了。所谓”纸上得来终觉浅,绝知此事要躬行“。今天小编就带着大家进行指针知识的练习,也相当与复习一遍学过的内容。我们进入正题,向着大厂进发!


一. sizeof和strlen

1.1sizeof

  1. 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;
}

1.2strlen

  1. strlen

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

 size_t strlen ( const char * str );

strlen函数是用来统计字符串个数的,统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。
strlen 函数会⼀直向后找 \0 字符,直到找到为止,所以可能存在越界查找
注意:strlen函数的使用需要包含头文件<string.h>

#include <stdio.h>
#include<string.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(arr1));return 0;
}

1.3sizeof和strlen对比

  • 本质:sizeof是操作符 , strlen是库函数。
  • 功能:sizeof计算空间大小,strlen统计字符个数。
  • 注意事项:sizeof不关注内存内容,只关注内存大小
    strlen通过观察内存的\0统计,遇到\0停下。若没有\0则可能产生越界现象。

二.数组名和指针加减

2.1数组名的理解

  • 数组名是数组首元素的地址。
    但有两个特殊情况
  • sizeof(数组名),此时的数组名表示整个数组, 计算的是整个数组的大小,单位是字节。
    &(数组名),此时的数组名也表示整个数组,取出的是整个数组的大小。
    注意括号里必须只有数组名!

2.2指针加减整数

  • 指针加减整数,指针向前或向后移动。
  • 指针加减移动多大距离(单位是字节),取决于指针类型
  • 举例:int类型的指针+1跳过一个整形,指向下一个整型。
    指针地址+4
    char类型的指针+1跳过一个字符,指向下一个字符。
    指针地址+1

2.3指针的大小

  • 指针大小取决于当前环境
  • 32位环境指针大小4字节
  • 64位环境指针大小8字节

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

3.1 一维数组

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a+0));//2
printf("%d\n",sizeof(*a));//3
printf("%d\n",sizeof(a+1));//4
printf("%d\n",sizeof(a[1]));//5
printf("%d\n",sizeof(&a));//6
printf("%d\n",sizeof(*&a));//7
printf("%d\n",sizeof(&a+1));//8
printf("%d\n",sizeof(&a[0]));//9
printf("%d\n",sizeof(&a[0]+1));//10
printf("%d\n",sizeof(a));//1
//数组名单独放在sizeof里面,
//计算整个数组的大小 4*4==16
printf("%d\n",sizeof(a+0));//2
//a没有单独放在sizeof里面,
//a就是首元素地址
//指针+0跳过0的整型元素,还是指向首元素,
//地址就是指针,指针的大小是4/8
printf("%d\n",sizeof(*a));//3
//a是数组首元素地址,*a就是首元素
//int类型,4字节大小
printf("%d\n",sizeof(a+1));//4
//a首元素地址,a+1跳过一个整型,指向第二个元素
//指针加减整数还是指针,大小4/8字节
printf("%d\n",sizeof(a[1]));//5
//a[1]就是数组第二个元素,大小为4字节
printf("%d\n",sizeof(&a));//6
//&a取出数组首元素地址,数组的地址也是指针
//计算指针的大小,4/8字节
printf("%d\n",sizeof(*&a));//7
//&a取出整个数组的地址,*(数组的地址)访问呢整个数组
//计算整个数组的大小,4*4==16
printf("%d\n",sizeof(&a+1));//8
//&a是整个数组的地址,类型是数组指针,+1跳过整个数组
//指向数组后第一个字节的地址,地址是指针
//大小4/8字节
printf("%d\n",sizeof(&a[0]));//9
//a[0]数组首元素,&a[0]取出数组首元素地址
//地址就是指针,4/8字节
printf("%d\n",sizeof(&a[0]+1));//10
//a[0]数组首元素,&a[0]取出数组首元素地址
//首元素地址+1跳过一个整型,指向第二个元素
//还是指针,4/8字节

  • 验证:
  • 64位环境:
    在这里插入图片描述
  • 32位环境:

3.2 字符数组

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7
printf("%d\n", sizeof(arr));//1
//arr数组名单独放在sizeof内部,计算整个数组的大小,1*6=6字节
printf("%d\n", sizeof(arr+0));//2
//arr是数组名,就是数组首元素的地址,+0跳过0的字节,指向首元素
//还是指针,4/8字节
printf("%d\n", sizeof(*arr));//3
//arr是数组首元素的地址,*arr解引用访问数组首元素,1字节
printf("%d\n", sizeof(arr[1]));//4
//arr[1]是数组第二个元素,1字节
printf("%d\n", sizeof(&arr));//5
//arr是数组名,&arr取出整个数组的地址,数组的地址也是地址
//还是指针,4/8字节
printf("%d\n", sizeof(&arr+1));//6
//&arr是整个数组的地址,+1跳过整个数组,指向数组后面的位置
//还是指针,4/8个字节
printf("%d\n", sizeof(&arr[0]+1));//7
//&arr[0]取出数组首元素的地址,+1跳过一个字节,指向第二个字符
//还是指针,4/8字节

  1. 验证:
  2. 64位环境:
  3. 32位环境:

char arr[] = {'a','b','c','d','e','f'};数组没有\0
printf("%d\n", strlen(arr));//1
//arr是数组名,数组首元素地址开始统计
//没有\0,什么时候遇到\0不知道,是随机值
printf("%d\n", strlen(arr+0));//2
//arr是数组名,是数组首元素地址,
//arr+0跳过0个字节,指向第一个元素,也是和上面一样的随机值
printf("%d\n", strlen(*arr));//3
//arr是数组名,是数组名首元素地址,*arr-'a'-ascllm码值97
//相当于把97作为地址传给strlen,strlen接收野指针,代码是错误的
printf("%d\n", strlen(arr[1]));//4
//arr[1]-'b'-98,把98传给strlen,也是野指针,也是错误的
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1))
printf("%d\n", strlen(arr));//1
//arr是数组名,数组首元素地址开始统计
//没有\0,什么时候遇到\0不知道,是随机值
printf("%d\n", strlen(arr+0));//2
//arr是数组名,是数组首元素地址,
//arr+0跳过0个字节,指向第一个元素,也是和上面一样的随机值
printf("%d\n", strlen(*arr));//3
//arr是数组名,是数组名首元素地址,*arr-'a'-ascllm码值97
//相当于把97作为地址传给strlen,strlen接收野指针,代码是错误的

printf("%d\n", strlen(arr[1]));//4
//arr[1]-'b'-98,把98传给strlen,也是野指针,也是错误的
printf("%d\n", strlen(&arr));//p1表示
//&arr取出数组的地址,数组的地址也指向数组首元素,设为x随机值
printf("%d\n", strlen(&arr+1));//p2表示
//&arr取出数组的地址,&arr+1跳过数组,指向数组后的位置,x-6的随机值
printf("%d\n", strlen(&arr[0]+1))//p3表示
//&arr[0]是数组首元素地址,&arr[0]+1跳过一个字节,指向第二个元素
//x-1的随机值

  • 验证:

3.3常量字符串

双引号里面的字符串就是常量字符串,常量字符串末尾自动补上\0.

char arr[] = "abcdef"//常量字符串,末尾自动补\0
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));//5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7
printf("%d\n", strlen(arr));//1
//arr是数组名,就是数组首元素地址,统计6个字符。
printf("%d\n", strlen(arr+0));//2
//arr是数组名,就是数组首元素地址,+0跳过0个字节
//还是数组首元素地址,//统计6个字符
printf("%d\n", strlen(*arr));//3
//arr是数组名,就是数组首元素的地址,*arr就是首元素'a'
//'a'的ascll码值是97相当于把97作为地址传递给strlen,strlen得到野指针
//此时代码是有问题的

printf("%d\n", strlen(arr[1]));//4
//arr[1]就是数组第二个元素,相当于把'b'--98传给strlen,
//也是野指针,也有问题
printf("%d\n", strlen(&arr));//5
//arr是数组名,&arr是数组首元素的地址,数组首元素的地址也指向首元素
//统计的还是6个字符
printf("%d\n", strlen(&arr+1));//6
//arr是数组名,&arr是数组首元素的地址,数组首元素的地址也指向首元素
//&arr+1跳过一个数组,指向数组后面的位置,什么时候遇到\0不知道
//所以是随机值
printf("%d\n", strlen(&arr[0]+1));//7
//&arr[0]取出数组首元素的地址,+1跳过一个字节,指向第二个字符,
//从第二个字符统计,统计5个字符

四.二维数组

4.1二维数组的理解


我们可以把二维数组看一个以数组为元素的一维数组。每行数组都有一个数组名,例如二位数组第一行的数组的数组名就是a[0],
第一行的数组的数组名就是a[1],以此类推。
举个例子来验证可不可以这样理解:
例如我们访问第二行第三个元素:
我们会写成a[1][2]
a[1]就是第二行的数组名,数组名就是数组首元素的地址
首元素地址再通过【2】就跳过2个元素,访问第三个元素,
就是第二行第三个元素。说明我们的理解是没问题的。

4.2二维数组练习

int a[3][4] = {0};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a[0][0]));//2
printf("%d\n",sizeof(a[0]));//3
printf("%d\n",sizeof(a[0]+1));//4
printf("%d\n",sizeof(*(a[0]+1)));//5
printf("%d\n",sizeof(a+1));//6
printf("%d\n",sizeof(*(a+1)));//7
printf("%d\n",sizeof(&a[0]+1));//8
printf("%d\n",sizeof(*(&a[0]+1)));//9
printf("%d\n",sizeof(*a));//10
printf("%d\n",sizeof(a[3]));//11
printf("%d\n",sizeof(a));//1
//数组名单独放在sizeof里,计算整个数组的大小,
//3*4*4=48
printf("%d\n",sizeof(a[0][0]));//2
//a[0][0]表示数组首元素,大小为4字节
printf("%d\n",sizeof(a[0]));//3
//第一行数组名单独放在sizeof里,计算的是第一行数组的大小
//4*4=16字节;
printf("%d\n",sizeof(a[0]+1));//4
//a[0]第一行数组的数组名,就是第一行首元素的地址,+1指向第一行第二个元素,
//还是指针,4/8个字节
printf("%d\n",sizeof(*(a[0]+1)));//5
//a[0]+1是第一行第二个元素的地址,*解引用访问第一行第二个元素,4字节
printf("%d\n",sizeof(a+1));//6
//a是二维数组的数组名,就是数组首元素的地址,就是第一行的地址
//+1跳过一行,指向第二行,还是指针,4/8字节
printf("%d\n",sizeof(*(a+1)));//7
//a+1是第二行的地址,*解引用访问第二行,计算第二行的大小
//4*4=16字节
printf("%d\n",sizeof(&a[0]+1));//8
//a[0]是第一行的数组名,&a[0]取出第一行数组的地址,
//&a[0]+1跳过一行,指向第二行,还是指针
//指针大小就是4/8
printf("%d\n",sizeof(*(&a[0]+1)));//9
//&a[0]+1第二行的地址,*解引用访问第二行的数组,计算第二行数组的大小
//4*4=16字节
printf("%d\n",sizeof(*a));//10
//a是二维数组的数组名,数组名就是数组首元素的地址,就是第一行的地址
//*解引用访问第一行,计算第一行的大小。4*4=16
printf("%d\n",sizeof(a[3]));//11
//a[3]看似越界,但是并未访问,sizeof根据类型推断。
//所以a[3]无需真实访问,根据类型推断为第四行的数组名
//数组名单独放在sizeof内部,计算第四行数组的大小,4*4=16

后言

这里就是今天跟大家分享的全部内容啦,今天的内容有点绕,但是大家直到抓紧指针加减和数组名理解这两个点,那就迎刃而解啦!今天就分享到这里,感谢小伙伴的耐心阅读。咱们下期见!拜拜~
在这里插入图片描述

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

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

相关文章

一文搞懂从爬楼梯到最小花费(力扣70,746)

文章目录 题目前知动态规划简介动态规划模版 爬楼梯一、思路二、解题方法三、Code 使用最小花费爬楼梯一、思路二、解题方法三、Code 总结 在计算机科学中&#xff0c;动态规划是一种强大的算法范例&#xff0c;用于解决多种优化问题。本文将介绍动态规划的核心思想&#xff0c…

吴恩达机器学习理论基础解读

吴恩达机器学习理论基础 机器学习最常见的形式监督学习&#xff0c;无监督学习 线性回归模型概述 应用场景一&#xff1a;根据房屋大小预测房价 应用场景二&#xff1a;分类算法&#xff08;猫狗分类&#xff09; 核心概念&#xff1a;将训练模型的数据称为数据集(学习数据…

MySQL学习笔记(二)

1、把查询结果中去除重复记录 2、连接查询 从一张表中单独查询&#xff0c;称为单表查询。emp表和dept表联合起来查询数据&#xff0c;从emp表中取员工名字&#xff0c;从dept表中取部门名字&#xff0c;这种跨表查询&#xff0c;多张表联合起来查询数据&#xff0c;被称为连…

信阳附大医院-市民心中的健康守护者

信阳附大医院,一所集医疗、预防、保健、科研、教学、康复于一体的现代化综合医院,坐落于信阳市工区路600号,是市卫生部门批准成立的医疗机构,更是市民心中的健康守护者. 医院环境优雅,设施先进,服务周到,汇聚了一支技术精湛、经验丰富的医疗团队.医师们以患者为中心,用心倾听,精…

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

皮具5G智能制造工厂数字孪生可视化平台&#xff0c;推进企业数字化转型。随着信息技术的快速发展&#xff0c;数字化转型已成为企业提升竞争力、实现可持续发展的关键路径。皮具行业&#xff0c;作为一个传统的手工制造业&#xff0c;正面临着巨大的市场变革和技术挑战。如何在…

一款轻量、干净的 Vue 后台管理框架

开始之前 在开始介绍之前我想谈谈为什么要自己做一个后台管理&#xff0c;我知道很多人都用一些开源的后台管理项目&#xff0c;这些老前辈有很多亮点值得学习&#xff0c;但是存在的一些问题同样不可忽视&#xff0c;我认为很多开发者会被困扰(仅代表个人观点) 技术栈老旧不升…

【Labview】虚拟仪器技术

一、背景知识 1.1 虚拟仪器的定义、组成和应用 虚拟仪器的特点 虚拟仪器的突出特征为“硬件功能软件化”&#xff0c;虚拟仪器是在计算机上显示仪器面板&#xff0c;将硬件电路完成信号调理和处理功能由计算机程序完成。 虚拟仪器的组成 硬件软件 硬件是基础&#xff0c;负责将…

ATAM方法架构评估实践

用ATAM方法评估软件体系结构&#xff0c;其工作分为4个基本阶段&#xff0c;即演示、调查和分析、测试和报告ATAM&#xff08;如图1所示&#xff09;。接下来分别就每个阶段的实践进行详细介绍。 图1 ATAM方法的评估实践阶段划分 1.阶段1——演示&#xff08;Presentation&…

2.SpringBoot利用Thymeleaf实现页面的展示

什么是Thymeleaf&#xff1f; Thymeleaf是一个现代服务器端Java模板引擎&#xff0c;适用于Web和独立环境&#xff0c;能够处理HTML&#xff0c;XML&#xff0c;JavaScript&#xff0c;CSS甚至纯文本。 Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这…

内存管理new and delete(C++)

在本篇中&#xff0c;将会较为详细的介绍在 Cpp 中的两个新操作符 new 和 delete&#xff0c;将会介绍其中的底层原理&#xff0c;以及这两个操作符的使用方法。其中还介绍了 new/delete 操作符使用的细节&#xff0c;还扩展了一些有关定位 new 表达式的知识点。最后总结了 mal…

【简单讲解下C++max函数的使用】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

动态支付策略:Go 语言中策略模式的妙用

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 在现代软件架构中&#xff0c;支付功能是不可或缺的一环。无论是在线购物还是虚拟服务&#xff0c;支付策略的选择直接影响用户体…