指针和数组在strlen和sizeof中的大小计算看这一篇就够了

操作符详解中,我们介绍到了sizeof操作符的作用,下面通过一些习题来进一步区分sizeof和strlen以及指针和数组在strlen和sizeof中的大小计算。(博主编译器为32位平台)


int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a+0));//(取决于平台) - 1的地址
	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));//跳过1个数组后的地址
	printf("%d\n", sizeof(&a[0]));//地址
	printf("%d\n", sizeof(&a[0]+1));//地址

	return 0;
}

答案为:
在这里插入图片描述

重点剖析:

  • 在这里插入图片描述
    &a取出的是整个数组的地址,再解引用得出的是整个数组的大小。因此为16个字节。

  • a+1和&a + 1的区别:
    (a + 1)相当于a + 1 * sizeof(int)
    (&a + 1)相当于&a + 1 * sizeof(a)
    💬​ a代表数组首元素的地址
    💬​&a代表整个数组的地址
    这也是它们加一造成的差异原因之一


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

在这里插入图片描述

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));//error
	//printf("%d\n", strlen(arr[1]));//error
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

在这里插入图片描述

strlen遇到\0才停止。
除下面两个表达式,其余结果均为随机值。
在这里插入图片描述
❓​为什么呢?
因为strlen函数接收的是指针,而*arr和arr[1]均为某一字符,传过去的是ASCII码值。会导致程序错误。


int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//计算长度(包括\0)
	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;
}

在这里插入图片描述

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//计算长度(不包括\0)
	printf("%d\n", strlen(arr + 0));//计算从第一个字符后字符串的长度
	//printf("%d\n", strlen(*arr));//error
	//printf("%d\n", strlen(arr[1]));//error
	printf("%d\n", strlen(&arr));//取出数组地址 - 还是看作从首元素地址开始计算
	printf("%d\n", strlen(&arr + 1));//跳过一个数组后寻找\0 - 获得随机值
	printf("%d\n", strlen(&arr[0] + 1));//跳过第一个字符后开始计算长度

	return 0;
}

在这里插入图片描述

在这里插入图片描述
此表达式结果为随机值。


int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//获得指针大小
	printf("%d\n", sizeof(p + 0));//地址
	printf("%d\n", sizeof(*p));//p指向首元素地址,解引用为1
	printf("%d\n", sizeof(p[1]));//第二个元素大小
	printf("%d\n", sizeof(&p));//地址
	printf("%d\n", sizeof(&p + 1));//地址
	printf("%d\n", sizeof(&p[0] + 1));//地址
	return 0;
}

在这里插入图片描述
在这里插入图片描述
p为指针,内存中存放a的地址,指向字符串的首个字符。计算p的长度即为计算地址的大小

int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 0));//5
	//printf("%d\n", strlen(*p));//error
	//printf("%d\n", strlen(p[1]));//error
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}

在这里插入图片描述
在这里插入图片描述
&p:p在内存中放的值完全不知道,所以为随机值


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));//代表首元素地址(即第一行地址) + 1 - 即第二行地址
	printf("%d\n", sizeof(*(a + 1)));//代表*(a+1) <=> a[1],第二行元素总大小
	printf("%d\n", sizeof(&a[0]+1));//&a[0]代表取出第一行的地址,+1代表取出第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//解引用,计算的是第二行
	printf("%d\n", sizeof(*a));//代表对第一行地址解引用,计算的是第一行元素总大小
	printf("%d\n", sizeof(a[3]));

	return 0;
}

在这里插入图片描述

重点剖析:
在这里插入图片描述
a[0]能代表第一行的数组名
在这里插入图片描述
乍一看,我们会觉得这种形式数组越界了,其实不然!要知道,sizeof( )里面的表达式不作实际的运算。因此,无论a[ ]里面是什么都不会影响计算


上面所有的题目,你做对了多少题呢?如果你全都做对了,那么恭喜你!如果有一些题目做错了,不必焦躁,勤练,你一定会成功的!

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值