c语言修炼之指针和数组笔试题解析(1.1)

前言

小伙伴们们让我们一起开始学习今天的内容吧!今天的内容超棒的哦!废话不多说,让我们开始学习叭!

1.一维数组

在开始之前我们需要来回忆一些相关知识点。sizeof是一个操作数用来计算类型所占空间的大小,计算时不包括\0。数组名表示首元素地址但是有两个例外:sizeof(数组名)计算的是整个数组的长度,&数组名取的是整个数组的地址。回忆结束直接上代码!

1.1整型数组

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

 变量在内存中开辟空间

 如上图,此时我们再来一个个分析代码叭

int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));

第一个求的是sizeof(a)的大小,哦豁,这刚好时上面提到的例外数组名单独放在sizeof中计算的是整个数组的地址!整型数组,一个元素的大小是4个字节一共有4个元素,那么此时整个数组的大小为16个字节!

printf("%d\n", sizeof(a+0));

再来分析一下,这里不是数组名单独放在sizeof内部,说明此时数组名表示首元素地址!a+0地址没有变化还是首元素的地址。地址的大小是4/8个字节!

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

这里依旧不是数组名单独放在sizeof内部,依旧表示数组首元素地址,就相当于&a[0],在进行解引用操作*(&a[0])得到a[0]也就是1,此时在计算大小就相当于sizeof(int)结果为4个字节

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

sizeof内部不是单独的数组名,a还是表示数组名首地址。a+1来到数组第二个元素的地址,&a[0]+1,地址的大小还是4/8个字节

printf("%d\n", sizeof(a[1]));

a[1]也就是数组第二个元素即2,此时得到的是4个字节

printf("%d\n", sizeof(&a));

 &数组名,表示拿到整个数组的地址,此时sizeof计算的是地址的大小。地址依然是4/8个字节

printf("%d\n", sizeof(*&a));

&和*会相互抵消,*&a就剩下了a,此时计算的是sizeof(a),计算的是整个数组的大小,结果为16个字节

printf("%d\n", sizeof(&a+1));

&a取出整个数组的地址,在进行加1会跳过一个数组的大小,此时sizeof计算的依旧是地址,结果是4/8个字节

printf("%d\n", sizeof(&a[0]));

&a[0]取出第一个元素的地址,sizeof计算的依旧是地址的大小,结果依然是4/8个字节

printf("%d\n", sizeof(&a[0]+1));

&a[0]+1取出的是数组第二个元素的地址,sizeof计算的依旧是地址的大小结果是4/8个字节

运行一下代码来看看结果叭,在vs中使用的是x86所以地址的大小是4字节

 1.2字符数组

还记得sizeof和strlen的区别吗?sizeof是一个操作数用来计算类型所占空间大小,不包含\0;strlen是一个库函数使用之前要引用头文件string.h,专门计算字符串大小遇到\0停止。字符数组的初始化有两种:char arr[]={'a','b'}和char arr[ ]="ab",二者的区别在于第二种初始化中隐藏个\0而第一种则没有

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr));
	return 0;

}

 来分析叭

printf("%d\n", sizeof(arr));

sizeof(数组名)求的是整个数组的地址,一个char类型大小为1个字节,字符数组有6个元素,那么整个数组的大小为6字节

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

 arr表示单独放在sizeof内部表示数组首元素的地址,arr+0依旧是数组首元素的地址!地址的大小是4/8个字节

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

arr还是表示数组首元素的地址,相当于&arr[0],在进行解引用*(&arr[0])-->arr[0],即sizeof计算的是数组第一个元素的大小,即1个字节

printf("%d\n", sizeof(arr[1]));

    这里直接计算的就是数组第二个元素的大小,结果为1字节

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

 &数组名,取得是整个数组的地址,所以sizeof计算的是地址的大小,结果为4/8

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

&arr取出整个数组的地址,加1之后跳过一个数组而大小,sizeof计算的还是地址的大小,结果为4/8

printf("%d\n", sizeof(&arr[0]+1));

&arr[0]取出数组第一个元素的地址,&arr[0]+1-->&arr[1]取出数组第二个元素的地址,sizeof计算的是地址的大小,结果为4/8

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

strlen计算遇\0之前的字符个数,但arr中没有\0。因此计算结果为随机值

printf("%d\n", strlen(arr+0));

arr+0依旧表示数组首元素的地址,依旧是因为没有\0,所以结果是随机值

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

arr表示数组首元素即&arr[0],*&arr[0]-->arr[0],所以可以变成strlen(arr[0]),根据cplusplus可以发现strlen的参数是char*的指针,所以此时计算得到的结果是error

printf("%d\n", strlen(arr[1]));

 解释同上,结果是error

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

 &arr取到的是整个数组的地址,此时strlen计算的是地址的大小,但由于arr中没有\0,结果依然是随机值

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

&arr取到的是整个数组的地址,&arr+1跳过一个数组的地址,由于依旧没有\0,结果依然是随机值

printf("%d\n", strlen(&arr[0]+1));

&arr[0]+1得到的是数组第二个元素的地址,但由于arr中没有\0,结果依然是随机值

运行一下看看结果叭

 再来一组不同的

int main()
{
	char arr[] = "abcdef";
	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));
	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));
	
	return 0;
}

来看看有什么不一样叭,貌似求得都一样只有字符数组不一样!

printf("%d\n", sizeof(arr));

sizeof(数组名)计算整个数组的大小,sizeof用于计算所占内存的大小包括\0.。所以计算结果为7

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

arr+0还是表示数组首元素的地址,地址的大小是4/8

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

*arr-->*(&arr[0])-->arr[0],sizeof计算数组第一个元素的大小,结果为1字节

printf("%d\n", sizeof(arr[1]));

sizeof计算数组第一个元素的大小,结果为1字节

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

&arr取出的是整个数组的地址,因此sizeof计算的是地址的大小,结果为4/8

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

&arr取出的是整个数组的地址,&arr+1跳过一整个数组的地址,sizeof计算的依旧是地址的大小,结果为4/8

printf("%d\n", sizeof(&arr[0]+1));

&arr[0]+1-->&arr[1],得到数组第二个元素的地址,sizeof计算的依旧是地址的大小,结果为4/8

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

char arr[]="abcdef"中隐藏了一个\0,strlen计算的是遇到\0之前的字符个数,因此结果为6

printf("%d\n", strlen(arr+0));

arr+0表示数组首元素的地址,strlen计算的是遇到\0之前的字符个数,因此结果为6

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

strlen的参数需要char*指针,*arr-->*&arr[0]-->arr[0],而不需要具体的数,因此结果为error

printf("%d\n", strlen(arr[1]));

解释同上

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

&arr取出的是整个数组的地址,但是&arr和&arr[0]的地址一样都是从数组首元素地址、

 那&arr和&arr[0]有什么区别呢,再用代码看看叭

int main()
	{
		char arr[] = "abcdef";
		printf("%p\n", &arr[0]);
		printf("%p\n", &arr[0] + 1);

		printf("%p\n", &arr);
		printf("%p\n", &arr + 1);
		return 0;
		
	}

会发现&arr[0]+1跳过了一个字节而&arr+1跳过了7个字节,为啥是七个字节呢,这是因为sizeof计算数组的大小是7字节

再回到这道题上来,strlen(&arr)还是从数组首元素地址开始计算遇到\0停止,结果为6

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

&arr+1哈哈上面有说到的情况欸,那么strlen(&arr+1)的结果是啥呢?没错又是随机值

printf("%d\n", strlen(&arr[0]+1));

&arr[0]+1-->&arr[1]得到的是数组第二个元素的地址,所以strlen在进计算时从第二个元素地址开始往后算,所以结果为5


ok,以上就是今天的学习啦,后面的内容明天再写啦

猜你喜欢

转载自blog.csdn.net/2301_77886098/article/details/131829922