• 【C语言】指针和数组笔试题解析


    大家好,我是苏貝,本篇博客带大家了解指针和数组笔试题解析,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
    在这里插入图片描述


    1.前言

    本篇文章是讲述在不同数组和指针的条件下,使用sizeof和strlen,让我们对数组和指针的理解更深。

    数组名一般表示首元素地址,除以下2种情况:
    1.sizeof(数组名),括号里面只有数组名,此时数组名表示整个数组,计算的是整个数组的大小
    2.&数组名,数组名表示整个数组,取出的是整个数组的地址

    指针变量的大小为4/8byte:
    1.在32位机器下,每个地址有32个比特位,即32/8=4个字节,所以指针变量的大小也为4个字节
    2.在64位机器下,每个地址有64个比特位,即64/8=8个字节,所以指针变量的大小也为8个字节

    2.一维数组

    思考下面代码的结果:

    int a[] = {1,2,3,4};
    printf("%d\n",sizeof(a));//1
    printf("%d\n",sizeof(a+0));//2
    printf("%d\n",sizeof(*a));//3
    printf("%d\n",sizeof(a+1));//4
    printf("%d\n",sizeof(a[1]));//5
    printf("%d\n",sizeof(&a));//6
    printf("%d\n",sizeof(*&a));//7
    printf("%d\n",sizeof(&a+1));//8
    printf("%d\n",sizeof(&a[0]));//9
    printf("%d\n",sizeof(&a[0]+1));//10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    结果:
    1.16byte;sizeof(数组名),括号里面只有数组名,此时数组名表示整个数组,计算的是整个数组的大小=4*sizeof(int)=16
    2.4/8byte;sizeof后面括号内不止有数组名,所以该数组名代表首元素地址而非整个数组,首元素地址+0=首元素地址,是地址就是4/8byte
    3.4byte;a是首元素地址,*a表示对首元素地址解引用找到首元素,首元素类型为int,所以sizeof(int)=4
    4.4/8byte;a是首元素地址,a+1是第二个元素的地址,是地址就是4/8byte
    5.4byte;a[1]是第二个元素,元素类型为int,所以sizeof(int)=4
    6.4/8byte;&a表示取出的是整个数组的地址,是地址就是4/8byte
    7.16byte;&a表示取出的是整个数组的地址,再对整个数组的地址解引用找到整个数组,整个数组的大小为16byte
    8.4/8byte;&a表示取出的是整个数组的地址,&a+1表示跳过整个数组后的地址(如下图),是地址就是4/8byte
    9.4/8byte;&a[0]表示取出首元素地址,是地址就是4/8byte
    10.4/8byte;&a[0]表示取出首元素地址,+1表示第二个元素的地址,是地址就是4/8byte

    在这里插入图片描述


    2.字符数组

    2.1

    char arr[] = {'a','b','c','d','e','f'};
    printf("%d\n", sizeof(arr));//1
    printf("%d\n", sizeof(arr+0));//2
    printf("%d\n", sizeof(*arr));//3
    printf("%d\n", sizeof(arr[1]));//4
    printf("%d\n", sizeof(&arr));//5
    printf("%d\n", sizeof(&arr+1));//6
    printf("%d\n", sizeof(&arr[0]+1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.6byte;sizeof(arr)表示整个数组的大小=6*sizeof(char)=6
    2.4/8byte;sizeof后面括号内不止有数组名,所以该数组名代表首元素地址而非整个数组,首元素地址+0=首元素地址,是地址就是4/8byte
    3.1byte;arr是首元素地址,*arr表示对首元素地址解引用找到首元素,首元素类型为char,所以sizeof(char)=1
    4.1byte;arr[1]是第二个元素,元素类型为char,所以sizeof(char)=1
    5.4/8byte;&arr表示取出的是整个数组的地址,是地址就是4/8byte
    6.4/8byte;&arr表示取出的是整个数组的地址,&arr+1表示跳过整个数组后的地址(如上图),是地址就是4/8byte
    7.4/8byte;&arr[0]表示取出首元素地址,+1表示第二个元素的地址,是地址就是4/8byte

    2.2

    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", strlen(arr));//1
    printf("%d\n", strlen(arr + 0));//2
    printf("%d\n", strlen(*arr));//3
    printf("%d\n", strlen(arr[1]));//4
    printf("%d\n", strlen(&arr));//5
    printf("%d\n", strlen(&arr + 1));//6
    printf("%d\n", strlen(&arr[0] + 1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.随机值;strlen计算的是’\0’之前的字符个数,arr是首元素地址,strlen(arr)表示从首元素开始,一直向后直至找到’\0’,由于数组arr中没有’\0’,所以strlen一直会找到数组外我们不确定的某一位置停下,所以为随机值
    2.随机值;arr+0表示的是首元素地址,然后同上
    3.错误(如下图);arr表示的是首元素地址,* arr表示对首元素地址解引用找到首元素’a’,字符在内存中存储的是字符的ASCII码值,a的ASCII码值=97。strlen函数的参数为const char * str是指针,站在strlen的角度,是将实参’a’–97当作地址,直接进行访问,这是非法访问,会报错
    4.错误(如下图);同3
    5.随机值;&arr的类型为char(*)[6],而strlen函数的参数类型为const char * ,所以将&arr强制类型转化为const char * 类型即为首元素地址,然后同1
    6.随机值;&arr+1的类型为char( *)[6],然后同5
    7.随机值;&arr[0] + 1是第二个元素的地址,然后同1
    在这里插入图片描述

    2.3

    char arr[] = "abcdef";
    printf("%d\n", sizeof(arr));//1
    printf("%d\n", sizeof(arr+0));//2
    printf("%d\n", sizeof(*arr));//3
    printf("%d\n", sizeof(arr[1]));//4
    printf("%d\n", sizeof(&arr));//5
    printf("%d\n", sizeof(&arr+1));//6
    printf("%d\n", sizeof(&arr[0]+1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.7byte;arr数组里面的元素实际为 ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘\0’,sizeof(数组名)=整个数组所占空间的大小=7*sizeof(char)=7
    2.4/8byte;sizeof里面不止有arr,所以此时的arr是首元素地址,arr+0也是首元素地址,是地址就是4/8byte
    3.1byte;sizeof里面不止有arr,所以此时的arr是首元素地址,再对地址进行解引用找到首元素,sizeof(首元素)=1byte
    4.1byte;
    5.4/8byte;&arr表示取出的是整个数组的地址,是地址就是4/8byte
    6.4/8byte;&arr表示取出的是整个数组的地址,&arr+1表示跳过整个数组后的地址,是地址就是4/8byte
    7.4/8byte;&arr[0]表示取出首元素地址,+1表示第二个元素的地址,是地址就是4/8byte

    2.4

    char arr[] = "abcdef";
    printf("%d\n", strlen(arr));//1
    printf("%d\n", strlen(arr+0));//2
    printf("%d\n", strlen(*arr));//3
    printf("%d\n", strlen(arr[1]));//4
    printf("%d\n", strlen(&arr));//5
    printf("%d\n", strlen(&arr+1));//6
    printf("%d\n", strlen(&arr[0]+1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.6byte;arr数组里面的元素实际为 ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘\0’,strlen计算的是’\0’之前的元素个数,arr是首元素地址,所以从首元素开始往后数,直到遇见’\0’停止,‘\0’之前有6个元素
    2.6byte;arr数组里面的元素实际为 ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,’\0’,strlen计算的是’\0’之前的元素个数,arr+0表示的是首元素地址,所以从首元素开始往后数,直到遇见’\0’停止,‘\0’之前有6个元素
    3.错误;arr表示的是首元素地址,* arr表示对首元素地址解引用找到首元素’a’,字符在内存中存储的是字符的ASCII码值,a的ASCII码值=97。strlen函数的参数为const char * str是指针,站在strlen的角度,是将实参’a’–97当作地址,直接进行访问,这是非法访问,会报错
    4.错误;arr[1]表示的是第二个元素’b’,字符在内存中存储的是字符的ASCII码值,b的ASCII码值=98。strlen函数的参数为const char * str是指针,站在strlen的角度,是将实参’b’–98当作地址,直接进行访问,这是非法访问,会报错
    5.6byte;&arr的类型为char(*)[6],而strlen函数的参数类型为const char * ,所以将&arr强制类型转化为const char * 类型即为首元素地址,然后同1
    6.随机值;&arr+1的类型为char( *)[6],表示跳过整个数组后的地址,然后同5
    7.5byte;&arr[0] + 1是第二个元素的地址,然后同1

    2.5

    char *p = "abcdef";
    printf("%d\n", sizeof(p));//1
    printf("%d\n", sizeof(p+1));//2
    printf("%d\n", sizeof(*p));//3
    printf("%d\n", sizeof(p[0]));//4
    printf("%d\n", sizeof(&p));//5
    printf("%d\n", sizeof(&p+1));//6
    printf("%d\n", sizeof(&p[0]+1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.4/8byte;“abcdef”是常量字符串,指针变量p里面存的是字符’a’的地址,而非整个常量字符串的地址。是指针(地址)就是4/8byte
    2.4/8byte;“abcdef”是常量字符串,指针变量p里面存的是字符’a’的地址,而非整个常量字符串的地址,p+1指向的是字符’a’的下一位即字符’b’,是指针(地址)就是4/8byte
    3.1byte;指针变量p里面存的是字符’a’的地址,所以对p解引用找到字符’a’,a所占空间大小为1byte
    4.1byte;p[0]= * (p+0)=‘a’,a所占空间大小为1byte
    5.4/8byte;sizeof里面的是指针变量的地址,是指针(地址)就是4/8byte
    6.4/8byte;&p+1表示跳过指针变量p的下一个地址,是地址就是4/8byte
    7.4/8byte;&p[0]+1==& * (p+0)+1==字符’b’的地址,是地址就是4/8byte

    2.6

    char *p = "abcdef";
    printf("%d\n", strlen(p));//1
    printf("%d\n", strlen(p+1));//2
    printf("%d\n", strlen(*p));//3
    printf("%d\n", strlen(p[0]));//4
    printf("%d\n", strlen(&p));//5
    printf("%d\n", strlen(&p+1));//6
    printf("%d\n", strlen(&p[0]+1));//7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果:
    1.6byte;常量字符串在结尾处有一个隐藏的’\0’,所以常量字符串实际为"abcdef\0",指针变量p里面存的是字符’a’的地址,strlen计算的是’\0’之前的元素个数,所以从字符’a’开始往后数,直到遇见’\0’停止,‘\0’之前有6个元素
    2.5byte;p+1指向的是字符’a’的下一位即字符’b’,从字符’b’开始往后数,直到遇见’\0’停止,‘\0’之前有5个元素
    3.错误;指针变量p里面存的是字符’a’的地址,对p解引用找到字符’a’,字符在内存中存储的是字符的ASCII码值,a的ASCII码值=97。strlen函数的参数为const char * str是指针,站在strlen的角度,是将实参’a’–97当作地址,直接进行访问,这是非法访问,会报错
    4.错误;p[0]== * (p+0)== ‘a’,站在strlen的角度,是将实参’a’–97当作地址,直接进行访问,这是非法访问,会报错
    5.随机值;&p表示取出指针变量p的地址,从指针变量p开始往后数,直到遇见’\0’停止,但是我们并不知道什么时候能遇见’\0’,所以为随机值
    6.随机值;&p+1表示跳过指针变量p后的地址,从跳过指针变量p后的地址所存的字符开始往后数,直到遇见’\0’停止,但是我们并不知道什么时候能遇见’\0’,所以为随机值
    7.5byte;&p[0]+1 == & * (p+0)+1==字符’b’的地址,从字符’b’开始往后数,直到遇见’\0’停止,'\0’之前有5个元素

    2.7

    int a[3][4] = {0};
    printf("%d\n",sizeof(a));//1
    printf("%d\n",sizeof(a[0][0]));//2
    printf("%d\n",sizeof(a[0]));//3
    printf("%d\n",sizeof(a[0]+1));//4
    printf("%d\n",sizeof(*(a[0]+1)));//5
    printf("%d\n",sizeof(a+1));//6
    printf("%d\n",sizeof(*(a+1)));//7
    printf("%d\n",sizeof(&a[0]+1));//8
    printf("%d\n",sizeof(*(&a[0]+1)));//9
    printf("%d\n",sizeof(*a));//10
    printf("%d\n",sizeof(a[3]));//11
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果:
    1.48byte;a单独在sizeof里面,求的是整个二维数组的大小=34sizeof(int)=48
    2.4byte;a[0][0]是第一行的第一个元素,类型为int,所以大小=4byte
    3.16byte;我们可以将二维数组理解为一维数组的数组,a[0]、a[1]、a[2]中存的分别为第一行元素,第二行元素,第三行元素,类型为int( * )[4],都是一维数组,所以sizeof后面单独有a[0]即一个一维数组名,意思是求第一行元素的大小=4 * sizeof(int)=16
    4.4/8byte;由3知,a[0]是数组名,sizeof后面不止有数组名,所以数组名表示首元素地址即第一行第一个元素的地址,再+1表示第一行第二个元素的地址,是地址就是4/8byte
    5.4byte;由4知,a[0]+1表示第一行第二个元素的地址,对地址进行解引用找到表示第一行第二个元素,其占空间内存大小为4byte
    6.4/8byte;sizeof后面不止有二维数组名a,所以a表示首元素地址即第一行的地址,再+1表示第二行的地址,是地址就是4/8byte
    7.16byte;由6知,a+1表示第二行的地址,对地址进行解引用找到表示第二行元素,其占空间内存大小为4 * sizeof(int)=16byte;也可以这样理解,* (a+1)==a[1],表示第二行元素,其占空间内存大小为4 * sizeof(int) =16byte
    8.4/8byte;a[0]是存第一行元素的数组,&后面直接跟数组名表示取出整个数组的地址,再+1表示a[1]即第二行元素的地址,是地址就是4/8byte
    9.16byte;由8知,&a[0]+1是第二行元素的地址,对地址进行解引用找到表示第二行元素,其占空间内存大小为4 * sizeof(int)=16byte;
    10.16byte;sizeof后面不止有数组名,所以数组名表示首元素地址,即第一行元素的地址,对地址进行解引用找到表示第一行元素,其占空间内存大小为4 * sizeof(int)=16byte;
    11.16byte;该二维数组没有第四行,所以sizeof(a[3])属于非法访问?不是的,编译器根据sizeof内部的类型计算所占空间内存大小,而不需要访问括号内的东西。比如int a=3; int i=sizeof(a),此时编译器不会去访问a,因为编译器知道a的类型,所以直接输出sizeof(int)=4。a[3]与a[0]它们的类型是一样的,sizeof(a[0])=16byte,所以sizeof(a[3])=16byte


    好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

  • 相关阅读:
    Jaeger的经典BUG原创
    [LeetCode]-队列&优先队列/堆
    Kubernetes(K8s)从入门到精通系列之十八:使用 Operator Lifecycle Manager(OLM) 安装operator
    如何在Win系统搭建Oracle数据库并实现远程访问【内网穿透】
    chatgpt赋能python:Python词法分析:理解语言的起点
    (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
    java基础10题
    【JS笔记】JSON对象和面向对象编程
    华为交换机 S5735S-L24P4S-A光接口接入光无法设置指定速率如百兆
    接口测试常问面试题
  • 原文地址:https://blog.csdn.net/qq_75000174/article/details/132962720