E30.【C语言】练习:sizeof和strlen的习题集(B)

Exercise 4:sizeof 字符串

求下列代码打印结果

cpp 复制代码
#define CRT_NO_WARNINGNESS 1
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%zd\n", sizeof(arr));
	printf("%zd\n", sizeof(arr + 0));
	printf("%zd\n", sizeof(*arr));
	printf("%zd\n", sizeof(arr[1]));
	printf("%zd\n", sizeof(&arr));
	printf("%zd\n", sizeof(&arr + 1));
	printf("%zd\n", sizeof(&arr[0] + 1));
	return 0;
}

答案速查:

x86环境

x64环境

分析:

☑ printf("%zd\n", sizeof(arr));

注意结果不是6!sizeof()计算占用内存空间的大小,不关心存放的数据,因此算上\0,结果为7(一个字符占一个字节)

☑ printf("%zd\n", sizeof(arr + 0));

arr+0代表首元素的地址,因此sizeof(地址);,结果为4/8

4/8含义:4或8个字节

x86环境:4个字节

x64环境:8个字节

☑ printf("%zd\n", sizeof(*arr));

*arr是首元素,因此sizeof(元素);,又因为char类型,结果为1

☑ printf("%zd\n", sizeof(arr1));

arr1是第二个元素,因此sizeof(元素);,又因为char类型,结果为1

☑ printf("%d\n", strlen(&arr));

&arr是取整个数组的地址,因此sizeof(地址);,结果为4/8

☑ printf("%zd\n", sizeof(&arr + 1));

&arr是取整个数组的地址,+1跳过整个数组,但仍然是sizeof(地址);,结果为4/8

☑ printf("%zd\n", sizeof(&arr0 + 1));

&arr0是取首元素的地址,+1第二个元素的地址,因此sizeof(地址);,结果为4/8

Exercise 5:strlen 字符串(指针版)

cpp 复制代码
#include <stdio.h>
int main()
{
	char* p = "abcdef";
	printf("%zd\n", sizeof(p));
	printf("%zd\n", sizeof(*p));
	printf("%zd\n", sizeof(p[0]));
	printf("%zd\n", sizeof(&p + 1));
	printf("%zd\n", sizeof(&p[0] + 1));
	return 0;
}

答案速查:

x86环境

x64环境

分析:

☑ printf("%zd\n", sizeof(p));

p是一个指针变量,也就是求指针变量的存储空间,结果为4/8

☑ printf("%zd\n", sizeof(*p));

*p解引用,是首字符a,占一个字节,结果为1

☑ printf("%zd\n", sizeof(p0));

p0两种理解方式

1.把字符串当作数组,p0就是第一个字符a

2.p0等价为*(p+0),解引用是字符a

结果为1

☑ printf("%zd\n", sizeof(&p + 1));

&p+1因此sizeof(地址);,结果为4/8

细节说明:

&p是取p的地址,+1则跳过p(+4个或8个字节)

x86下

输入&p

输入&p+1

恰好跳过了完整的p(d8 7b 9e 00)

因此&p+1不是单纯的地址+1!!

☑ printf("%zd\n", sizeof(&p0 + 1));

&p0是字符a的地址,+1是字符b的地址,结果为4/8

Exercise 6:sizeof 二维数组

cpp 复制代码
#include <stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%zd\n", sizeof(a));
	printf("%zd\n", sizeof(a[0][0]));
	printf("%zd\n", sizeof(a[0]));
	printf("%zd\n", sizeof(a[0] + 1));
	printf("%zd\n", sizeof(*(a[0] + 1)));
	printf("%zd\n", sizeof(a + 1));
	printf("%zd\n", sizeof(*(a + 1)));
	printf("%zd\n", sizeof(&a[0] + 1));
	printf("%zd\n", sizeof(*(&a[0] + 1)));
	printf("%zd\n", sizeof(*a));
	printf("%zd\n", sizeof(a[3]));
	return 0;
}

答案速查:

x86环境

x64环境

分析:

☑ printf("%zd\n", sizeof(a));

**sizoef(数组名);**计算整个数组的大小 3*4*4=48bytes,结果为48

☑ printf("%zd\n", sizeof(a00));

单个元素,结果为4

☑ printf("%zd\n", sizeof(a0));

二维数组是一维数组的数组,a0指第0行的数组名,结果为16(4*4=16bytes)

☑ printf("%zd\n", sizeof(a0 + 1));

对比上一个,a0没有单独放入sizeof,这里的a0代表a00的地址,+1为a01的地址

结果为4/8

☑ printf("%zd\n", sizeof(*(a0 + 1)));

对a0+1解引用,为a01,大小4bytes,结果为4

☑ printf("%zd\n", sizeof(a + 1));

a没有单独放入sizeof中,这里的a代表首元素的地址,也是第一行的地址,+1代表跳过第一行至第二行,为第二行的地址,结果为4/8

**********区分a+1和a0+1**********

☑ printf("%zd\n", sizeof(*(a + 1)));

由上一个可知,解引用的是第一行的元素,一共4*4=16bytes,结果为16

或这样理解:*(a+1)等同于a1

☑ printf("%zd\n", sizeof(&a0 + 1));

&a0 + 1为第一行的地址(第0行+1),因此sizeof(地址);,结果为4/8

☑ printf("%zd\n", sizeof(*(&a0 + 1)));

对第1行地址解引用,一行4元素,4*4=16bytes,结果为16

☑ printf("%zd\n", sizeof(*a));

a没有单独放入sizeof中,这里的a代表首元素的地址,也是第一行的地址,解引用后4*4=16bytes

结果为16

☑ printf("%zd\n", sizeof(a3));

a3明显越界 (sizeof没有参与运算,没有访问内存,不称为越界)尽管第3行不存在,但是其类型是确定的

总结E29和E30:

数组名的意义:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。

往期推荐

E29.【C语言】练习:sizeof和strlen的习题集(A)

相关推荐
知识的宝藏34 分钟前
Xpaht self::div 轴语法
开发语言
keykey6.35 分钟前
卷积神经网络(CNN):让AI学会“看“
开发语言·人工智能·深度学习·机器学习
ss27335 分钟前
【入门OJ题解】分苹果问题(Python/Java/C 实现)
java·c语言·python
IsJunJianXin38 分钟前
谷歌搜索cookie NID逆向生成
开发语言·python·google搜索·sgss·nid-cookie·算法生成nid·google-cookie
weikecms1 小时前
美团霸王餐报名API接口
java·开发语言
你怎么知道我是队长1 小时前
CRC校验C语言实现-CRC8、CRC16、CRC16的直接计算法、查表法
c语言·前端·javascript
淘源码d1 小时前
医院专业级PACS系统完整源码(C+VC+MSSQL)
c语言·数据库·sqlserver·源码·pacs系统·医学影像系统
繁星蓝雨1 小时前
C++中对比pragma once和ifndef的使用区别
开发语言·c++·ifndef·头文件·pragma once
.千余1 小时前
【C++】C++手写Vector容器:从底层源码模拟实现
开发语言·c++·经验分享·笔记·学习
a诠释淡然1 小时前
C++ vs Rust:哪个更适合你的下一个项目?
开发语言·c++·rust