sizeof和strlen对数组,指针笔试题运算


我们要使用sizeof和strlen对数组,指针笔试题运算,那么就必须先了解strlen,sizeof和数组名的含义。

了解strlen和sizeof

1.1sizeof

sizeof 计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。

sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。

你可以放指针类型,结果就是4或者8个字节(指针的大小与系统的位数相关,即在32位系统上,指针大小为4个字节(32位),而在64位系统上,指针大小为8个字节(64位))。
在这里插入图片描述

你放的是int类型,结果就是4个字节。你放的是char类型,结果就是1个字节。
其它类型以此类推,只关注数据占用内存的大小,不关心里面是什么数据

1.2strlen

strlen 是C语⾔库函数,功能是求字符串⻓度,统计的是 \0 之前字符的个数。使⽤需要包含头⽂件 string.h
我们使用strlen函数时要注意strlen函数里面存放的数据是地址strlen是通过地址来访问数据的,直到访问的地址内部存放的数据内部是\0字符才停止运算.

如果strlen函数里面存放的数据不是地址而是字符的话,编译器会自动将字符转换为它们对应的ASCll码值,以与ASCll值大小相同的地址为起点进行访问

如果strlen函数里面存放的数据不是地址而是数字的话以与数值大小相同的地址为起点进行访问
这两种都是传输野指针给strlen,代码是有问题的运行不起来,所以我们在使用尽量符合strlen的运算规则,放地址在strlen函数,而不放其它类型数据。
在这里插入图片描述

了解数组名

既然我们我们要使用sizeof和strlen来和数组相结合运算,我们肯定要了解数组名的含义。

  1. sizeof(数组名),这⾥单独出现的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
  2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
    在这有一个要点:整个数组的地址等于数组中首元素地址
一维数组
&arr==arr==&arr[0]//&arr是整个数组的地址等于数组中首元素地址,arr是首元素地址,所以(&arr==arr)
//arr是首元素地址,&arr[0]也是首元素地址,所以(arr==&arr[0])
二维数组
&arr==arr==&arr[0]==&arr[0][0]
//&arr是整个数组的地址等于数组中首元素地址,arr是首元素地址,所以(&arr==arr)
//arr是首元素地址也是第一行地址等于&arr[0],所以(arr==&arr[0])
//第一行又可看作是一个一维数组,
//整个一维数组的地址&arr[0]等于数组中首元素地址&arr[0][0],所以(&arr[0]==&arr[0][0])
  1. 除此之外所有的数组名都表⽰⾸元素的地址。
//一维数组
 char arr1[] = "ftrbh";
 一维数组的数组名就是arr1
 //二维数组
 char arr2[3][4] = { '0' };
二维数组的数组名为arr2
二维数组有三行四列,和一维数组有所差距的是:
它每一行都可看作为一个一维数组,所以有多少行就有————多少个行数组名和行首元素地址:
 arr[0]是第一行的首元素地址也是第一行的数组名;
 arr[1]是第二行的首元素地址也是第二行的数组名;
 arr[2]是第三行的首元素地址也是第三行的数组名;
有三行所以有三个行首元素地址。
二维数组有多个数组名所以运算是要更加注意。

数组和指针笔试题解析

    int a[] = { 1,2,3,4 };//数组有几个元素?

	printf("%zd\n", sizeof(a));
	//16 -- sizeof(数组名)的场景,计算整个数组,有四个元素,每个元素有4个字节,总共有16个字节。
	
	printf("%zd\n", sizeof(a + 0));
	//a是首元素的地址,没有单独出现在sizeof内部-类型是int*, a+0 还是首元素的地址,是地址大小就是4/8
	
	printf("%zd\n", sizeof(*a));
	//a是首元素的地址,*a就是首元素,大小就是4个字节
	
	printf("%zd\n", sizeof(a + 1));
	//a是首元素的地址,类型是int*,a+1跳过1个整型指针,a+1就是第二个元素的地址,既然是地址那么结果就是4/8
	
	printf("%zd\n", sizeof(a[1]));
	//a[1]就是第二个元素,int类型,大小4个字节
	
	printf("%zd\n", sizeof(&a));
	//&a符合&数组名类型,是表示整个数组的地址,数组的地址也是地址,类型为int*,大小就是4/8个字节
	
	printf("%zd\n", sizeof(*&a));
	//1. *& 互相抵消了,sizeof(*&a) = sizeof(a) -16
	//2. &a 是数组的地址,对数组指针解引用访问的是整个数组, 计算的是整个数组的大小 -16
	
	printf("%zd\n", sizeof(&a + 1));
	//&a+1是跳过整个数组后的那个位置的地址,类型为int*,就是4/8个字节
	
	printf("%zd\n", sizeof(&a[0]));
	 //首元素的地址,类型为int*,大小4/8个字节
	
	printf("%zd\n", sizeof(&a[0] + 1));
	//&a[0] + 1 -- 数组第二个元素的地址,类型为int*,大小是4/8个字节
char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));
	//数组名单独放在sizeof内部了,计算的是数组的大小,有6个元素,每个元素字节为1个单位,结果为6
	
	printf("%d\n", sizeof(arr + 0));
	//arr没有单独放在sizeof内部,所以arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8个字节
	
	printf("%d\n", sizeof(*arr));
	//arr没有单独放在sizeof内部,arr是首元素的地址,*arr就是首元素,大小就是1个字节
	//*arr -- arr[0] - *(arr+0)
	
	printf("%d\n", sizeof(arr[1]));
	//arr[1] 是第二个元素,大小也是1个字节
	
	printf("%d\n", sizeof(&arr));
	//&arr 是数组地址,数组的地址也是地址,类型为char*,是指针类型,大小是4/8个字节
	//&arr -- char (*)[6]
	
	printf("%d\n", sizeof(&arr + 1));
	//&arr+1, 跳过整个数组,指向了数组后边的空间,访问还是指针类型,4/8个字节
	
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8字节
    char arr[] = { 'a','b','c','d','e','f' };
	
	printf("%d\n", strlen(arr));
	//arr是首元素的地址,从首元素开始访问,数组中没有\0,就会导致越界访问,结果是随机值
	
	printf("%d\n", strlen(arr + 0));
	//arr+0是数组首元素的地址,数组中没有\0,就会导致越界访问,结果就是随机的
	
	printf("%d\n", strlen(*arr));
	//arr是首元素的地址,*arr是首元素,就是'a','a'的ascii码值是97
	//就相当于把97作为地址传递给了strlen,strlen得到的就是野指针, 代码是有问题的
	
	printf("%d\n", strlen(arr[1]));//arr[1]--'b'--98,传给strlen函数也是错误的
	
	printf("%d\n", strlen(&arr));
	//&arr是整个数组的地址,起始位置是数组的第一个元素的地址,数组中没有\0,就会导致越界访问,结果是随机值 
	
	printf("%d\n", strlen(&arr + 1));
	//随机值 
	
	printf("%d\n", strlen(&arr[0] + 1));
	//从第2个元素的地址开始向后统计的,得到的也是随机值 
	    char arr[] = "abcdef";
		
		printf("%d\n", sizeof(arr));
		//arr是数组名,单独放在sizeof内部,计算的是数组总大小,是7个字节
		
		printf("%d\n", sizeof(arr + 0));
		//arr表示数组首元素的地址,arr+0还是首元素的地址,是地址就是4/8
		
		printf("%d\n", sizeof(*arr));
		//arr表示数组首元素的地址,*arr就是首元素,大小是1字节
		
		printf("%d\n", sizeof(arr[1]));
		//arr[1]是第二个元素,大小1个字节
		
		printf("%d\n", sizeof(&arr));
		//&arr是数组的地址,是地址就是4/8
		
		printf("%d\n", sizeof(&arr + 1));
		//&arr是数组的地址,+1跳过整个数组,还是地址,是地址就是4/8个字节
		
		printf("%d\n", sizeof(&arr[0] + 1));
		//&arr[0] + 1是第二个元素的地址,大小是4/8个字节

    char arr[] = "abcdef";
	
	printf("%d\n", strlen(arr));
	//从首元素的地址开始访问,访问6个字节后遇见\0,结果为6
	
	printf("%d\n", strlen(arr + 0));//arr首元素的地址,arr+0还是首元素的地址,向后在\0之前有6个字符
	
	printf("%d\n", strlen(*arr));
	//'a'-97, 就相当于把97作为地址传递给了strlen,strlen得到的就是野指针, 代码是有问题的
	
	printf("%d\n", strlen(arr[1]));
	//'b'-98, 就相当于把98作为地址传递给了strlen,strlen得到的就是野指针, 代码是有问题的出错
	
	printf("%d\n", strlen(&arr));
	//&arr是数组的地址,也是从数组第一个元素开始向后找,结果是6

	printf("%d\n", strlen(&arr + 1));
	//&arr是数组的地址,+1跳过整个数组,因为不知道访问多少个字节才能遇见\0,所以结果为随机值
	
	printf("%d\n", strlen(&arr[0] + 1));
	//&arr[0]是数组首元素的地址,+1跳过整个一个元素,因为不知道访问多少个字节才能遇见\0,所以结果为随机值
    int a[3][4] = { 0 };
	
	printf("%d\n", sizeof(a));
	//a是数组名,单独放在sizeof内部,计算的是数组的大小,单位是字节 - 48 = 3*4*sizeof(int)
	
	printf("%d\n", sizeof(a[0][0]));
	//a[0][0] 是第一行第一个元素,大小4个字节 
	
	printf("%d\n", sizeof(a[0]));
	//a[0]第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小 16 个字节
	
	printf("%d\n", sizeof(a[0] + 1));
	//a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部,所以这里的数组名a[0]就是
	//数组首元素的地址,就是&a[0][0],+1后是a[0][1]的地址,大小是4/8个字节

	printf("%d\n", sizeof(*(a[0] + 1)));
	//*(a[0] + 1)表示第一行第二个元素,大小就是4
	
	printf("%d\n", sizeof(a + 1));
	//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是
	//第一行的地址,a+1,跳过一行,指向了第二行,a+1是第二行的地址是指针,是地址大小就是4/8个字节

	printf("%d\n", sizeof(*(a + 1)));
	//1.a+1是第二行的地址,*(a+1)就是第二行,计算的是第二行的大小 - 16
	
	printf("%d\n", sizeof(&a[0] + 1));
	//a[0]是第一行的数组名,&a[0]取出的就是数组的地址,就是第一行的地址
	//&a[0]+1 就是第二行的地址,是地址大小就是4/8个字节
	
	printf("%d\n", sizeof(*(&a[0] + 1)));
	//*(&a[0] + 1)意思是对第二行的地址解引用,访问的就是第二行,大小是16字节
	
	printf("%d\n", sizeof(*a));
	//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是
	//第一行的地址,*a就是第一行,计算的就是第一行的大小,16字节
	//*a == *(a+0) == a[0]
	
	printf("%d\n", sizeof(a[3]));
	//a[3]无需真实存在,仅仅通过类型的推断就能算出长度
	//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16个字

以上就是与sizeof和strlen有关的数组,指针笔试题运算。各位宝子们觉得还行吗?多提点意见,我会一一阅读更改。谢谢。

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明fei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值