sizeof和strlen的使用及差异

sizeof

1.sizeof是操作符

2.sizeof计算操作数所占内存的大小,单位是字节(byte)

3.sizeof不关注内存中存放什么数据

4.sizeof比较通用不挑类型

strlen

1.strlen是库函数,使用需包含头文件string.h

2.strlen是求字符串长度的,统计的是 \0 之前的字符的个数

3.strlen关注内存中是否有 \0 ,如果没有 \0 ,就会持续向后找,可能会越界

4.strlen只能用于求字符串长度

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

0802861d6b73433cb66b3a6790380552.png

 

 当sizeof后接类型名时,()不可省

cd0ec8a34fd245bf942a11e5d3fbd791.png

在这里,介绍一个类型size_t , size_t是专门设计给sizeof的,用于表示sizeof的返回值类型,即无符号整数类型,在打印时也可使用%zd代替%d 

下面为一段sizeof应用实例

#include<stdio.h>
int main()
{
	short s = 10;
	int i = 2;
	int n = sizeof(s = i + 4);
	printf("%d\n", n);
	printf("%d\n", s);
	return 0;
}

请问:输出结果为多少

87b94557f1d4477b89cb05a30bbfe3d6.jpeg

输出结果:

0ec664dda9a54bcebf52bf5b5f0228ca.png

n的值为什么为2呢?

因为sizeof在计算大小的时候是根据类型推算的

short类型大小为两个字节,int类型大小为四个字节

我们无法将四米长的棍子放进两米长的房间,同样的,我们也无法将int类型的数据完整存放在short类型中,此时就要发生截断,所以n的值为2

s的值为什么是10呢?

当sizeof的操作数为表达式时,表达式是不参与计算的

为什么表达式放到sizeof中就不参与计算了呢?

我们知道,表达式有两个属性:

1.类型属性

2.值属性

sizeof根据类型属性推断

源文件(源代码)----------编译--------链接--------可执行程序-----------计算/运算

test.c                                sizeof                           test.exe                    s=i+4

sizeof(s=i+4)在编译时就已确定大小,即在编译时发生了

int n=sizeof(s=i+4);------------>int n=2;

因为在编译时表达式就已被替换,所以后续计算失效,s=i+4 根本不执行,所以sizeof里面的表达式不参与计算

你是否明晰了sizeof的使用呢?做几道题检测一下吧

🌰:一:

#include<stdio.h>
int main()
{
	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));
	return 0;
}

df09ff793f624220b9929def2f95ca54.jpeg

c73cab02390149578e9f2fa096bfc73d.png

想作对这道题,除了了解sizeof的使用,还需知晓数组名的含义

数组名的含义 

数组名即为数组首元素地址,但有两个例外

🌰1:sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节

🌰2:&数组名,数组名表示整个数组,取出的是整个数组的地址

知晓了以上内容我们再来分析这道题 

1.数组名单独放在sizeof内部,计算整个数组的大小(4*4=16)

2.数组名没有单独放在sizeof内部,此时数组名为首元素地址,a+0还是数组首元素地址,地址大小为4/8字节(取决于编译环境)

3.对数组首元素地址解引用,得到的是数组首元素,数组首元素类型为int,大小为4字节

4.a+1为数组第二个元素的地址即&a[1],地址大小为4/8字节(取决于编译环境)

5.a[1]计算第二个元素大小,由于该元素类型为int,所以结果为4字节

6.&a取出的为整个数组的地址,但数组的地址也是地址,地址大小不会改变(不会因为是数组地址就变大或是char类型的变量就变小),大小就是4/8字节

7.(1).*&相互抵消sizeof(*&a)==sizeof(a),计算的为整个数组的大小

   (2).&a先取出整个数组的地址

              而*(解引用操作符)到底访问多少由指针类型决定,此时指针的类型为int(*)[4],故访问整个数组

8.*&a访问的是整个数组,&a+1跳过的也为整个数组,此时计算的是a数组后面的那个地址,地址大小为4/8字节

9.数组首元素地址,大小4/8

10.数组第二个元素的地址,大小4/8

🌰二: 

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	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));
	return 0;
}

f4cf9d9aed4e401592a18d467d6b8afd.jpeg

efee69c292b442e0ad5255fdb63bad80.png

1.sizeof数组名,计算整个数组的大小,即为1*6=6字节

2.数组首元素地址,大小为4/8字节

3.*arr得到的为数组首元素,数组首元素类型为char,大小为1字节

4.arr[i]==*(arr+i),arr[1]即为数组第二个元素

5.整个数组的地址也是地址,大小为4/8字节

6.&arr+1跳过整个数组,指针指向的为数组后面那个元素,地址大小为4/8字节

7.&arr[0]+1为数组第二个元素的地址,大小为4/8字节

🌰三:

#include<stdio.h>
int main()
{
	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]));
	return 0;
}

be1eff97fa9346b3ba7e87560ce211ae.png

 1.sizeof(数组名)计算的为整个数组的大小,即为48(3*4*4)字节

2.a[0][0]为数组第一个元素,大小为4字节

3.a[0]就是第一行的数组名,单独放在sizeof内部,计算的为第一行的大小,即为4*4=16

4.a[0]是第一行数组名,但数组名并未单独放在sizeof内部,所以数组名表示的是数组首元素地址,也就是a[0][0]的地址,a[0]+1是a[0][1]的地址,地址的大小为4/8字节

5.a[0]+1即&a[0][1],对该指针进行解引用操作,即元素a[0][1],由于是整形二维数组,元素为整形,大小为4字节

6.a没有单独放在sizeof内部,数组名a就是数组首元素的地址,也就是第一行的地址,a+1就是第二行的地址,地址大小为4/8字节

7.对第二行地址解引用访问第二行,大小为4*4=16字节

8.&a[0]取出的是第一行的地址,&a[0]+1得到的就为第二行的地址,地址大小4/8字节

9.对第二行地址解引用访问第二行,大小为4*4=16字节

10.数组名a就是数组首元素的地址,也就是第一行的地址,*a就是访问第一行,大小为4*4=16字节          -->                  *a ==*(a+0)==a [ 0 ];

11.a[3]和a[0]性质相同,sizeof不会访问内容,大小仍为16字节

strlen

strlen是C语言库函数,功能为求字符串长度,统计的为从strlen函数的参数地址向后,\0 之前字符串中字符的个数,strlen函数会一直向后查找  \0 字符,直到找到为止,所以可能存在越界查找与提前终止。

下面来几段应用实例

代码1:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	return 0;
}

这段代码打印结果为6,向后查找至 \0 停止,\0 不计入总数(sizeof中\0计入总数)

55cae8afa98c43519b59faa1c2804ea9.png

 代码2:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abc\0def";
	printf("%d\n", strlen(arr));
	return 0;
}

这段代码运行结果为3,遇见 \0 提前终止

代码3:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c' };
	printf("%s\n", arr);
	printf("%d\n", strlen(arr));
	return 0;
}

这段代码的输出结果为 abc+随机值  和 随机值,在初始化时未加入终止字符(\0)导致打印字符串其后为随机值,strlen函数向后越界查找遇见 \0 才停止

7b53ecb3fef34ebea597e16f82e78dab.jpeg

会了没会了没会了没

再做几道题试试吧!!!

🌰一:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen (*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
}

下面不想写上面不想看,就这样吧看得开心就行。。。

我要爬山去了(西上北下)

 

 

  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
ESP32和STM32之间的串口通信可以通过以下步骤实现: 1. 首先,需要确定通信的串口参数,如波特率、数据位、停止位、奇偶校验等。 2. 在ESP32和STM32上分别配置串口参数,并将它们连接在一起。通常情况下,ESP32的TX引脚连接到STM32的RX引脚,ESP32的RX引脚连接到STM32的TX引脚。 3. 在ESP32和STM32上分别编写串口通信程序。例如,ESP32可以使用Arduino IDE中的Serial对象,而STM32可以使用HAL库中的UART接口。 4. 在通信过程中,需要注意数据的传输顺序。对于单字节数据,可以直接发送和接收;对于多字节数据,需要考虑字节顺序和字节对齐等问题。 下面是一个简单的示例代码,用于在ESP32和STM32之间进行串口通信: ESP32代码: ```c++ void setup() { Serial.begin(115200); // 设置串口参数 } void loop() { Serial.write("Hello, STM32!"); // 发送数据 delay(1000); } ``` STM32代码: ```c++ void UART_Init(void) { // 初始化串口参数 huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } } int main(void) { UART_Init(); // 初始化串口 while (1) { uint8_t buffer[16]; HAL_UART_Receive(&huart2, buffer, sizeof(buffer), 1000); // 接收数据 HAL_UART_Transmit(&huart2, "Hello, ESP32!", strlen("Hello, ESP32!"), 1000); // 发送数据 HAL_Delay(1000); } } ``` 请注意,以上代码仅供参考,具体实现可能会因硬件和软件环境的不同而有所差异

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值