详解------>数组笔试题(必备知识)

目录

本章将通过列题进一步了解sizeof 与strlen的区别,加强对数组的理解。

1:一维数组列题

2:字符数组列题

3:二维数组列题


        首先在进行这些习题讲解之前我们需要知道的知识点

                sizeof:是一个关键字,可以计算变量,数据类型,函数所占空间的大小,单位是字节,计算的时候只关心数据类型

                strlen:是一个标准库函数,头文件是   <striing.h>,是用来计算字符串\0前面的字符的个数,strlen(数组名)。

        还有对于数组名的理解:除了2种情况数组名就是首元素的地址,1:单独使用sizeof(数组名),这里的数组名指的是整个数组。2:&数组名,这里的数组名代表的是整个数组,所以&数组名代表的是整个数组的地址,它的指向也是数组的首元素的地址,但是在进行指针加减整数的时候跳过的是整个数组。

1:一维数组列题

        

#include<stdio.h>
int main()
{
    int a[] = {1,2,3,4};

    printf("%d\n",sizeof(a));//这里是特殊的情况,所以计算的是整个数组的大小 16

    printf("%d\n",sizeof(a+0));
    //这里的a是首元素的地址,+0后还是首元素地址,而地址(指针)的大小为4/8

    printf("%d\n",sizeof(*a));
    //a是首元素的地址,所以*a则代表数组中的第一个元素,所以大小为一个int的大小 4
    printf("%d\n",sizeof(a+1));
    //a代表数组首元素的地址,+1则代表指针指向2的地址,还是个地址所以大小为  4/8
    printf("%d\n",sizeof(a[1]));
    //a[1],代表数组中第二个元素即2,所以大小为int的大小   4
    printf("%d\n",sizeof(&a));
    //这里的a是特殊情况,所以a代表整个数组,但是&a还是一个地址  所以大小为 4/8
    printf("%d\n",sizeof(*&a));
    //这里有两种理解方式
    1:&a是代表数组的地址,* &a则代表数组  所以大小为数组的大小  16  *&  相当于没有
    2:&a本质上是数组指针,类型为int (*)[4],解引用后为类型int [4]  还是整个数组  16
    printf("%d\n",sizeof(&a+1));
    //&a+1代表的是地址,所以大小为4/8  但是在内存中表示为指针跳过整个数组,指向数组最后一个元素的后面
    printf("%d\n",sizeof(&a[0]));
    //这里就直接表示为取出第一个元素的地址,大小为  4/8
    printf("%d\n",sizeof(&a[0]+1));
    //这里表示第2个元素的地址,也是4/8,指针加一跳过一个int
}

这是在32位平台下的结果

64位平台下的结果

图解:a,a+1,&a,&a+1,&a[0],&a[0]+1

2字符数组

        形式1:

        

    //关于sizeof
char arr[] = {'a','b','c','d','e','f'};

printf("%d\n", sizeof(arr));
//这里代表整个数组的大小,为      6
printf("%d\n", sizeof(arr+0));
//这里的arr代表数组的首元素的地址,所以为  4/8
printf("%d\n", sizeof(*arr));
//这里的arr代表数组首元素的地址,所以*arr代表字符'a'   为1
printf("%d\n", sizeof(arr[1]));
//arr[1]代表,'b'    为1
printf("%d\n", sizeof(&arr));
//&arr代表整个数组的地址,所以为     4/8
printf("%d\n", sizeof(&arr+1));
//&arr+1表示跳过数组arr,指向下一个数组   4/8
printf("%d\n", sizeof(&arr[0]+1)); //也等于&arr[1]
//这里代表取出 字符'b'的地址,也是   4/8

   // 关于strlen
printf("%d\n", strlen(arr));
//这里的值为随机值,因为不知道内存中/0在哪
printf("%d\n", strlen(arr+0));
//这里的arr还是指的是数组首元素的地址,而strlen需要一个字符串,所以代码是error的
printf("%d\n", strlen(*arr));
//这里的*arr代表的是'a',而我们strlen需要char* 的参数,而'a'的asc码值为97,则会将代码段区域的 //地址传给strlen,这段代码块不是我们的内存,所以会形成非法访问内存的情况,所以也是error的
printf("%d\n", strlen(arr[1]));
//这里arr[1],代表的是'b',同理也是错误的只是asc变成98了  error
printf("%d\n", strlen(&arr));
//&arr代表的是整个数组的地址,但是它的值还是第一个元素的地址,沿着第一个元素向后寻找,所以也为随机值
printf("%d\n", strlen(&arr+1));
//同理,这是代表跳过数组后的地址,也是随机值,与前面一个相差  6
printf("%d\n", strlen(&arr[0]+1));
//这里代表'b'的地址,与arr差值为1

  32位平台下:

      

64位平台下:

形式2:

int main()
{
	char arr[] = "abcdef";//字符串中多了一个 '\0'

	printf("%d\n", sizeof(arr));
    //这里的arr代表整个数组,所以 大小为               7
	printf("%d\n", sizeof(arr + 0));
    //arr代表数组首元素地址 所以为                    4/8
	printf("%d\n", sizeof(*arr));
    //arr代表数组首元素,*arr则代表数组中的第一个元素   1
	printf("%d\n", sizeof(arr[1]));
    //arr[1]代表 'b',所以值为                        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));  
    //这里表示指向'b'的地址                           4/8

	printf("%d\n", strlen(arr));//strlen求得是字符串'/0'前面的元素个数
    //arr,表示数组的首元素地址,                      6
	printf("%d\n", strlen(arr + 0));
    //arr还是数组首元素的地址                         6
	printf("%d\n", strlen(*arr));
    //*arr代表的是'a',asc为97,strlen需要char* 所以改语句是error的
	printf("%d\n", strlen(arr[1]));
    //这个arr[1]代表数组的第2个元素即'b'同理,也会error
	printf("%d\n", strlen(&arr));
    //表示数组的地址,但是值还是与&arr[0]相等          6
	printf("%d\n", strlen(&arr + 1));
    //这个为随机值,&arr+1代表跳过整个数组后的地址   随机值
	printf("%d\n", strlen(&arr[0] + 1));
    这个代表的是'b'的地址,所以值为                    5
}

32位平台:

64位平台下:

为了理解上面的两个字符串的差异,我们可以通过画图来理解:

常量字符串:

        

char *p = "abcdef";//首先这个代码的理解是在代码段中存储着"abcdef"这个字符串,而p则是代表存储着这个字符串的地址

printf("%d\n", sizeof(p));
//这里的p是一个字符指针,所以大小为                        4/8
printf("%d\n", sizeof(p+1));
//指针加1且为char*指针,p+1代表指向b的地址                 4/8
printf("%d\n", sizeof(*p));
//char*指针解引用只访问1个字节内容,*p代表 'a'              1   
printf("%d\n", sizeof(p[0]));
//p[0]表示*(p+0)-->*p    'a'                              1
printf("%d\n", sizeof(&p));
//&p代表的是指向p地址的指针,是一个char**指针               4/8
printf("%d\n", sizeof(&p+1));
//&p+1是跳过1个字符指针的指针                              4/8
printf("%d\n", sizeof(&p[0]+1)); 
//即&p[1]-->&(p+1),也就是b的地址                          4/8


printf("%d\n", strlen(p));
//p的值为a的地址                                          6
printf("%d\n", strlen(p+1));
//p+1代表'b'的地址                                        5
printf("%d\n", strlen(*p));
//error的*p为 'a'
printf("%d\n", strlen(p[0]));
//error  p[0],代表的是'a'
printf("%d\n", strlen(&p));
//随机值,这里的&p代表的是存储p的地址                       随机值
printf("%d\n", strlen(&p+1));
//这里是跳过一个二级字符指针后面的地址                      随机值
printf("%d\n", strlen(&p[0]+1));
//这里代表首元素地址+1,表示'b'的地址所以值为                5

     

3:二维数组 

        

int a[3][4] = {0};

printf("%d\n",sizeof(a));
//这里的a代表的是整个数组,所以值为                                     48
printf("%d\n",sizeof(a[0][0]));
//a[0][0]代表第一个元素                                                4
printf("%d\n",sizeof(a[0]));
//a[0]可以看作二维数组的首元素为一个一维数组                            16
printf("%d\n",sizeof(a[0]+1));
//a[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表示首元素的地址,即1维数组的地址  int(*)[4],+1则代表指向第二个一维数组的地址   4/8   
printf("%d\n",sizeof(*(a+1)));
//表示第二个一维数组    大小为                                         16
printf("%d\n",sizeof(&a[0]+1));
//&a[0]表示一维数组的地址,类型为int(*)[4],+1则代表指向第二个二维数组的地址   4/8
printf("%d\n",sizeof(*(&a[0]+1)));
//第二个二维数组的大小                                                     16
printf("%d\n",sizeof(*a));
//a代表首元素的地址,即一维数组的地址,*a则代表一位数组                     16
printf("%d\n",sizeof(a[3]));
//a[3],虽然数组存在越界,但是sizeof只关注类型,所以a[3]                   16

 32位平台下:

 64位平台下:

总而言之,我们需要知道核心的知识点才不会被题目带偏。

        感谢观看!

猜你喜欢

转载自blog.csdn.net/2201_75964502/article/details/131611500