C语言深入理解指针(5)

文章目录

    • 一、sizeof和strlen的对比
        • 1、sizeof
        • 2、strlen
        • 3、sizeof和strlen的对比
    • 二、数组和指针笔试题解析
        • 1、一维数组
        • 2、字符数组
        • 3、二维数组


一、sizeof和strlen的对比

1、sizeof

siezeof是一个操作符,sizeof计算的是变量所占内存空间大小,单位是字节,操作数也可以是类型要用()括号扩起来,计算的是类型创建所占内存空间的大小。
sizeof只关注占用内存的大小,不在乎内存中存放什么数据。

#include<stdio.h>
int main()
{
	int a = 10;
	printf("%zd\n", sizeof(a));
	printf("%zd\n", sizeof a);
	printf("%zd\n", sizeof(int));
	return 0;
}

在这里插入图片描述

2、strlen

strlen库函数使用时,需引入头文件<string.h>
strlen是C语言库函数,功能求字符串长度。函数原型如下:

size_t strlen ( const char * str );

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

#include <stdio.h>
#include<string.h>
int main()
{
	char arr1[3] = { 'a', 'b', 'c' };
	char arr2[] = "abc";
	printf("%d\n", strlen(arr1));
	//arr1初始化后没有\0,打印的值随机
	printf("%d\n", strlen(arr2));
	//arr2后加\0,打印结果为3

	printf("%zd\n", sizeof(arr1));
	//只有三个char类型的数据,占用3个字节的空间
	printf("%zd\n", sizeof(arr2));
	//arr2后加了\0,有四个char类型的数据,占用4个字节的空间
	return 0;
}

在这里插入图片描述

3、sizeof和strlen的对比
sizeof strlen
1、sizeof是操作数
2、sizeof计算操作数所占内存的大小单位是字节
3、不关注内存中存放什么数据
4、返回值为size_t 类型无符号整形
1、strlen是库函数,使用时需包含头文件string.h
2、strlen是求字符串长度,统计的是\0之前字符的个数,在字符串中使用
3、关注内存是否有\0,如果没有\0,,就会持续往后找,可能会越界
4、返回值为size_t类型无符号整形

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

1、一维数组
#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%zd\n", sizeof(a));
	//sizeof里面单独出现数组名,数组名代表整个数组的长度,为16字节

	printf("%zd\n", sizeof(a + 0));
	//sizeof里面没有单独出现数组名,数组名代表首元素地址,首元素地址 a + 0,等于&a[0],是地址4/8个字节

	printf("%zd\n", sizeof(*a));
	//sizeof里没有单独出现数组名,数组名代表首元素地址,首元素地址解引用,等于 a[0] == 1, 结果为4个字节

	printf("%zd\n", sizeof(a + 1));
	//首元素地址 &a[0] +1 ,等于 &a[1], 是地址大小为 4 / 8个字节

	printf("%zd\n", sizeof(a[1]));
	//a[1]等于 *(a + 1) ,a[1]代表数组第二个元素 2, 2的类型为int,大小为4

	printf("%zd\n", sizeof(&a));
	//&a,取地址数组名代表整个数组的地址,是地址大小为4/8个字节

	printf("%zd\n", sizeof(*&a));
	//&a,取地址数组名代表整个数组的地址,*&a,解引用整个数组的地址,代表整个数组的大小,类型为 int[4],大小为16个字节

	printf("%zd\n", sizeof(&a + 1));
	//&a,取地址数组名代表整个数组的地址,&a + 1,代表整个数组后面的地址,是地址4/8个字节

	printf("%zd\n", sizeof(&a[0]));
	//&a[0],取地址元素,是地址4/8个字节

	printf("%zd\n", sizeof(&a[0] + 1));
	//&a[0]+1,等于&a[1],是第二个元素的地址,是地址4/8个字节
	return 0;
}

在这里插入图片描述

2、字符数组

代码1:

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	//sizeof里面单独出现数组名代表整个数组的大小大小为6个字节

	printf("%d\n", sizeof(arr + 0));
	//arr+0,代表&a[0]首元素地址,是地址4/8个字节

	printf("%d\n", sizeof(*arr));
	//数组名代表首元素地址,*arr 是数组第一个元素 'a',类型为char 大小为1个字节

	printf("%d\n", sizeof(arr[1]));
	//arr[1]数组中的二个元素'b',类型为char,大小为1个字节

	printf("%d\n", sizeof(&arr));
	//&arr代表整个元素的地址,是地址大小为4/8个字节

	printf("%d\n", sizeof(&arr + 1));
	//&arr + 1,个个数组的地址加1,数组的末尾地址,是地址大小4/8个字节

	printf("%d\n", sizeof(&arr[0] + 1));
	//&arr[0]+1,是数组中第二个元素的地址,&arr[1],是地址大小4/8个字节
	return 0;
}

在这里插入图片描述


代码2:

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", strlen(arr));
	//字符串后面没有\0,随机值

	printf("%zd\n", strlen(arr + 0));
	//首元素地址,没有结束标志\0,随机值

	//printf("%zd\n", strlen(*arr));
	//是首元素'a',把字符'a',97当成地址访问,崩溃

	//printf("%zd\n", strlen(arr[1]));
	//把第二个元素'b',98当成地址访问,崩溃

	printf("%zd\n", strlen(&arr));
	//整个数组的地址,起始地址跟首元素地址一样,随机值

	printf("%zd\n", strlen(&arr + 1));
	//整个数组的地址加一,指向的是&arr[7],越界,随机值

	printf("%zd\n", strlen(&arr[0] + 1));
	//二个元素的地址&a[1],没有\0结束,随机值
	return 0;
}

在这里插入图片描述

代码3:


#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", sizeof(arr));
	//数组名单独出现在sizeof里面,数组名代表整个数组的大小,整个数组后面隐藏了一个\0,大小为7个字节

	printf("%zd\n", sizeof(arr + 0));
	//首元素地址,是地址大小为4/8个字节

	printf("%zd\n", sizeof(*arr));
	//首元素,大小为1个字节

	printf("%zd\n", sizeof(arr[1]));
	//第二个元素'b',大小1个字节

	printf("%zd\n", sizeof(&arr));
	//&数组名,代表整个数组的地址,是地址大小为4/8

	printf("%zd\n", sizeof(&arr + 1));
	//整个数组的地址加一,还是地址,大小为4/8

	printf("%zd\n", sizeof(&arr[0] + 1));
	//第二个元素的地址,是地址大小为4/8
	return 0;
}

在这里插入图片描述
代码4:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";//后面自动加了\0
	printf("%zd\n", strlen(arr));
	//数组名代表首元素地址,\0之前有 6 个字符

	printf("%zd\n", strlen(arr + 0));
	//首元素地址,6

	//printf("%zd\n", strlen(*arr));
	//'a'的值97当成地址访问,崩溃

	//printf("%zd\n", strlen(arr[1]));
	//'b'的值当成地址访问,崩溃

	printf("%zd\n", strlen(&arr));
	//&数组名代表整个数组的地址,传参会形参接收用的是char*,就从首元素访问找\0,6

	printf("%zd\n", strlen(&arr + 1));
	//真个数组的地址加一指向的是数组后的地址,随机值

	printf("%zd\n", strlen(&arr[0] + 1));
	//第二个元素的地址找\0, 5
	return 0;
}

在这里插入图片描述
代码5:

#include<stdio.h>
int main()
{
	char* p = "abcdef";//指针指向常量字符串,首字符的地址
	printf("%zd\n", sizeof(p));
	//指针变量的大小,char*,4/8

	printf("%zd\n", sizeof(p + 1));
	//b字符的地址,是地址4/8

	printf("%zd\n", sizeof(*p));
	//首字符'a',大小为char 1个字节

	printf("%zd\n", sizeof(p[0]));
	//p[0] = *(p+0),首字符'a',大小1

	printf("%zd\n", sizeof(&p));
	//p变量的地址,是地址4/8

	printf("%zd\n", sizeof(&p + 1));
	//地址加一还是地址,是地址4/8

	printf("%zd\n", sizeof(&p[0] + 1));
	//首字符的地址加一,变成第二个字符的地址,是地址4/8
	return 0;
}

在这里插入图片描述
代码6:

#include<stdio.h>
int main()
{
	char* p = "abcdef";//后面有\0
	printf("%zd\n", strlen(p));
	//首字符地址,结果为 6

	printf("%zd\n", strlen(p + 1));
	//第二个字符地址,5

	//printf("%zd\n", strlen(*p));
	//字符’a'被当成地址访问崩溃

	//printf("%zd\n", strlen(p[0]));
	//等于*(p+0),首字符被当成地址访问,崩溃

	printf("%zd\n", strlen(&p));
	//变量p的地址,往后找\0,随机值

	printf("%zd\n", strlen(&p + 1));
	//变量p的地址加一,随机值

	printf("%zd\n", strlen(&p[0] + 1));
	//第二个字符'b'的地址,5
	return 0;
}

在这里插入图片描述

3、二维数组
#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%zd\n", sizeof(a));
	//整个数组的大小,12个int类型的元素,48

	printf("%zd\n", sizeof(a[0][0]));
	//第一行第一列元素,int类型,4

	printf("%zd\n", sizeof(a[0]));
	//第一行地址,代表整行的大小类型为int[4],16

	printf("%zd\n", sizeof(a[0] + 1));
	//第一行,第二列地址, 是地址 4 /8

	printf("%zd\n", sizeof(*(a[0] + 1)));
	//第一行第二列元素,int类型 4

	printf("%zd\n", sizeof(a + 1));
	//第一行地址加一,第二行地址 ,是地址 4 /8

	printf("%zd\n", sizeof(*(a + 1)));
	//第二行地址,第二行大小,16
	
	printf("%zd\n", sizeof(&a[0] + 1));
	//第二行地址是地址 4/8

	printf("%zd\n", sizeof(*(&a[0] + 1)));
	//第二行大小,16

	printf("%zd\n", sizeof(*a));
	//第一行地址,16

	printf("%zd\n", sizeof(a[3]));
	//第三行地址,16
	return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Photoshop 首选项设置建议

Windows Ps菜单&#xff1a;编辑/首选项 Edit/Preferences 快捷键&#xff1a;Ctrl K macOS Ps菜单&#xff1a;Photoshop/首选项 Photoshop/Preferences 快捷键&#xff1a;Cmd K 对 Photoshop 的首选项 Preferences进行设置&#xff0c;可以提高修图与设计效率。下面是一些…

Android 使用kotlin Retrofit2 + Dagger2完成网络请求跟依赖注入组合使用

文章目录 &#xff08;一&#xff09;引入依赖&#xff08;二&#xff09;基本概念Dagger中的基本概念&#xff1a;Retrofit介绍 &#xff08;三&#xff09;Dagger2 Module 和 Provides 和 Component Inject&#xff08;四&#xff09;Retrofit2 创建数据类Bean跟Service服务&…

GIt快速入门(一文学会使用Git)

GIt快速入门 文章目录 GIt快速入门一、为什么要学习Git二、Git的安装1.安装Git2.下载GUI 三、Git的概念1、版本控制2、集中式控制3、分布式控制4、多人协作开发1.并行开发2.分支管理3.冲突解决4.代码审查5.分布式特性 四、Git客户端操作1.界面介绍2.提交操作3.创建分支4.合并分…

网络I/O模型

网络I/O模型 同步I/O阻塞I/O非阻塞I/OI/O多路复用select函数接口示例 poll函数接口示例 poll 和 select 的区别epoll原理&#xff1a;示例 异步I/O 同步I/O 阻塞I/O 一个基本的C/S模型如下图所图&#xff1a;其中 listen()、connect()、write()、read() 都是阻塞I/O&#xff0…

Java面试题:Redis2_解决Redis缓存击穿问题

缓存击穿 当一个key过期时,需要对这个key进行数据重建 在重建的时间内如果有大量的并发请求进入,就会绕过缓存进入数据库,会瞬间击垮DB 重建时间可能因为数据是多个表的混合结果需要分头统计而延长,从而更容易出现缓存击穿问题 缓存击穿的解决方案 添加互斥锁 先查询缓存…

电商商城管理系统

前言&#x1f440;~ 将近一个月没更新了&#xff0c;最近忙着学校的大作业&#xff0c;一个是微信小程序的、一个是互联网编程的&#xff0c;也是忙完了这个大作业&#xff0c;这个大作业前端使用了vue、后端使用了java&#xff0c;接下来展示一些效果图&#xff0c;如果有需要…

2024 第三届 AIGC 中国开发者大会:多模态大模型的发展与趋势

引言 在2024年第三届AIGC中国开发者大会上&#xff0c;零一万物联合创始人潘欣分享了多模态大模型的发展与趋势。潘欣对多模态大模型的历史、现状和未来进行了详细回顾和深刻思考&#xff0c;为我们揭示了该领域的发展路径和技术前景。本文将详细解读潘欣的分享内容&#xff0…

如何搜索[仅有1个文件]或[指定个数范围、名称、类型文件等复杂情况]的文件夹

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 打开工具&#xff0c;切换到批量复制板块&#xff0c;用Ctrl5可以快速切换 然后鼠标移动到工具的贴边的右侧&#xff0c;不是移出工具外面&#xff0c;还在…

RT_thread nano移植Finsh

参考连接: https://blog.csdn.net/baseball214/article/details/131341722 移植的前提是,你已经有一个可以使用的nano功能. 1.将rtthread-nano-master\rt-thread\components文件复制到工程. 2.添加Finsh中的.c以及相关.h头文件路径 3.注释掉finsh_config.h文件中以下两个宏…

颠仆流离学二叉树2 (Java篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

使用autodl服务器进行模型训练

1.注册并且选择一个服务器租用 2.点击jupyter lab进入服务器内部 3.把yolov5-master这个的压缩文件上传到jupyter的文件列表中 4.打开终端 (1)查看目录 ls (2)解压yolov5-master(1) unzip "yolov5-master (1).zip" 可以看到解压成功&#xff01; (3)进入yolov5-m…

网桥、路由器和网关有什么区别

在计算机网络领域&#xff0c;网桥、路由器和网关都是常见的网络设备&#xff0c;它们在网络通信中扮演着不同的角色。虽然它们都有连接不同网络的功能&#xff0c;但在实际应用中却具有各自独特的作用和特点。 1.网桥&#xff08;Bridge&#xff09; 定义&#xff1a;网桥是…

【云原生】Kubernetes----配置资源管理Secrets与ConfigMaps

目录 一、Secrets &#xff08;一&#xff09;Secrets概述 &#xff08;二&#xff09;Secrets类型 &#xff08;三&#xff09;Secrets使用方式 &#xff08;四&#xff09;创建Secrets 1.陈述式命令创建 1.1 定义用户与密码文件 1.2 使用陈述式命令创建 2.使用base6…

每日一题《leetcode--LCR 022.环形链表||》

https://leetcode.cn/problems/c32eOV/ 我们使用两个指针&#xff0c;fast 与 slow。它们起始都位于链表的头部。随后slow 指针每次向后移动一个位置&#xff0c;而fast 指针向后移动两个位置。如果链表中存在环&#xff0c;则fast 指针最终将再次与slow 指针在环中相遇。 stru…

飞腾D2000+FPGA云终端,实现从硬件、操作系统到应用的完全国产、自主、可控

飞腾云终端基于国产化飞腾高性能8核D2000处理器平台的国产自主可控解决方案&#xff0c;搭载昆仑国产化固件,支持UOS、银河麒麟等国产操作系统&#xff0c;满足国产化信息安全运算的需求&#xff0c;实现从硬件、操作系统到应用的完全国产、自主、可控&#xff0c;是国产信息安…

排序进阶----快速排序

当我们写了插入和希尔排序后&#xff0c;我们就应该搞更难的了吧。大家看名字就知道我们这篇博客的内容了吧。而且从名字上来看。快速排序就很快吧。那么为什么这个排序怎么能叫快速排序啊。我们希尔排序不是很快嘛。那么我们的快速排序肯定是有特殊之处嘞。不然这就太自负了。…

【简单讲解下Fine-tuning BERT,什么是Fine-tuning BERT?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

paddleocr快速入门:基于python脚本及命令行两种方式实现图片OCR识别

本篇将再讲讲paddleocr在图像OCR识别方面的应用。 一、paddlecor参数说明 字段说明默认值use_gpu是否使用GPUTRUEgpu_mem初始化占用的GPU内存大小8000Mimage_dir通过命令行调用时执行预测的图片或文件夹路径page_num当输入类型为pdf文件时有效&#xff0c;指定预测前面page_nu…

R语言ggplot2包绘制世界地图

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 1. 数据读取与处理 首先&#xff0c;从CSV文件中读取数据&#xff0c;并计算各国每日收入的平均签证成本。 library(tidyverse) ​ df <- read_csv("df.csv") %>% group_…

MAC帧

基本问题 数据链路层的协议有很多&#xff0c;但是都有三个基本问题&#xff1a;封装成帧&#xff0c;透明传输和差错检测。 封装成帧 封装成帧&#xff08;Framing&#xff09;就是在一段数据的前后分别添加首部和尾部&#xff0c;这样就构成了一个帧。帧是数据链路层的传送…