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


    指针是C语言的灵魂,他的玩法多种多样,这篇文章带来指针的笔试题详解,可以帮助我们更好的理解与巩固指针的知识


    题目比较多,但切记戒骄戒躁,保持空杯心态,相信看完一定会有提升
    开始之前要先来一点预备知识:

    预备知识:

    数组名:

    数组名大部分情况下是首元素地址,但有两种情况例外
    1.当sizeof(数组名),此时数组名代表整个数组,求出的是整个数组的大小,单位是字节。
    2.当&数组名,此时数组名代表整个数组,取出的是整个数组的地址,虽然与首元素地址相同,但含义不一样。

    sizeof:

    sizeof是一个操作符,可以求变量(类型)所占空间的大小。

    strlen:

    strlen是一个为库函数,可以获取字符串\0之前的长度

    一一一一一一一一一分割线一一一一一一一一一一

    题目:

    分为两部分,第一部分时一维数组,第二部分是二维数组,逐步攀升难度

    假设都在32位机器下进行

    一维数组:

    第一组:

    //一维数组
    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
    • 12

    答案:

    1.16
    a代表整个数组,每个数组元素是int类型,一共4个元素,故为16字节大小
    2.4
    a为首元素地址,当地址进行±运算时,与指针类型有关,a的类型为int*,所以+0时,地址会向前跳过0个整形,仍旧是首元素地址
    3.4
    a为首元素地址,当解引用时,得到的是arr[0],也就是第一个整形元素,大小为4
    4.4
    a为首元素地址,当地址进行±运算时,与指针类型有关,a的类型为int*,所以+1时,地址会向前跳过1个整形,而数组是连续存放的,故地址会指向第二个数组元素。
    5.4
    a[1]是一个整形,为数组第二个整形元素,大小是4字节
    6.4
    &数组名代表的是取出整个元素的地址,但不管是什么地址,在32位下地址都是4个字节大小
    7.16

    此题有两种解法:
    1.*与&结合会相互抵消,数组名在sizeof中就是求出整个数组的大小
    2.&数组名取出的是整个数组的地址,当地址进行解引用时,与指针类型有关,解引用一个数组指针类型的内容,就会访问一个大小为此数组的内容,即4个整形变量的数组,大小为16字节

    8.4
    a代表整个数组,当地址进行±运算时,与指针类型有关,而此数组指针的类型是 int(*)[4], 数组指针+1会跳过一个数组,也就是跳过4个整形的数组,而运算后的结果仍旧是地址,故答案为4
    9.4
    &a[0]代表的是第一个元素的地址,地址大小为4字节
    10.4
    &a[0]代表的是第一个元素的地址,当地址进行±运算时,与指针类型有关,整形指针+1会跳过一个整形,即&a[0]+1指向数组第二个元素,为第二个元素的地址,大小为4个字节

    一一一一一一一一一分割线一一一一一一一一一一
    第二组:

    //字符数组
    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
    • 9

    答案:
    1.6
    arr在sizeof中为整个数组,求出的是整个数组的大小,单位是字节,结果为6字节
    2.4
    arr此时为首元素地址,类型为char*,字符指针+0会跳过0个字符大小,此时仍指向首元素地址,地址大小为4字节
    3.1
    arr此时为首元素地址,类型为char*,解引用arr会访问一个char大小的内容,为数组第一个元素,大小为1字节
    4.1
    arr[1]代表数组第二个元素,类型为char,大小为1字节
    5.4
    arr代表整个数组,取出的是整个数组的地址,地址的大小为4字节
    6.4
    arr代表整个数组,取出的是整个数组的地址,当地址进行±运算时,与指针类型有关,数组指针的类型为 char (*)[6] ,数组指针+1会跳过一个数组,在这就是跳过6个字符,运算后的结果依然是地址,大小为4
    7.4
    &arr[0]代表第一个元素的地址,当地址进行±运算时,与指针类型有关,字符指针+1会跳过一个字符,&arr[0]+1代表第二个元素地址,大小为4字节
    一一一一一一一一一分割线一一一一一一一一一一
    第三组:

    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.随机值
    arr为首元素地址,但arr数组中没有’\0’,故结果为随机值
    2.随机值
    arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+0会向前跳过0个字符,地址不变,而arr数组中没有’\0’,故结果为随机值
    3.err
    arr为首元素地址,*arr为第一个元素’a’,传入strlen中会把a的ASCII码值当做地址,而此地址为野指针,会报错。
    4.err
    arr[1]为数组第二个元素’b’,传入strlen中会把b的ASCII码值当做地址,而此地址为野指针,会报错。
    5.随机值
    arr为整个数组地址,首先要知道strlen的参数为在这里插入图片描述
    传入strlen后数组指针会被强转为char *类型,而他们两的值是一样的,故结果为随机值
    6.随机值
    arr为整个数组地址,当地址进行±运算时,与指针类型有关,数组指针+1会向前跳过一个数组,故此时地址为跳过一个数组的地址,由于不清楚什么时候遇到’\0’,故为随机值
    7.随机值
    &arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过一个字符,故此时地址为跳过一个字符的地址,由于不清楚什么时候遇到’\0’,故为随机值
    一一一一一一一一一分割线一一一一一一一一一一
    第四组:

    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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    答案:
    1.7
    arr代表整个数组,在sizeof中会求出整个数组的大小,为7字节,因为写成字符串形式自带’\0’
    2.4
    arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故此时地址为跳过一个字符的地址,则结果为4
    3.1
    arr为首元素地址,类型为char* ,解引用时会访问一个字节,为’a’,字符a的大小为1的字节
    4.1
    arr[1]为数组中第二个元素的地址,为char类型,大小为1字节
    5.4
    arr为整个数组地址,&arr为整个元素的地址,是地址就是4个字节
    6.4
    arr为整个数组地址,&arr为整个元素的地址,类型为char(*)[7],数组指针+1会跳过1个数组,&arr+1为跳过一个数组后的地址,是地址大小就是4字节
    7.4
    &arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故此时地址为跳过一个字符的地址,则结果为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.6
    arr为首元素地址,因为字符串自带\0,故传入首元素地址后会得到\0之前的字符串个数,也就是6
    2.6
    arr为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+0会向前跳过0个字节,故传入首元素地址后会得到\0之前的字符串个数,也就是6
    3.err
    arr为首元素地址,解引用后得到字符a,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
    4.err
    arr[1]为字符b,会将字符b的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
    5.6
    arr为整个数组地址,&arr为整个元素的地址,传入strlen后数组指针会被强转为char *类型,而他们两的值是一样的,故结果为6

    6.随机值
    arr为整个数组地址,&arr为整个元素的地址,类型为char(*)[7],数组指针+1会跳过1个数组,&arr+1为跳过一个数组后的地址,传入strlen后数组指针会被强转为字符指针类型
    7.5
    arr[0]为数组首元素,&arr[0]为首元素地址,当地址进行±运算时,与指针类型有关,字符指针+1会向前跳过1个字符,故得到的结果为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
    p为字符指针,是指针大小就为4字节
    2.4
    p+1指向数组第二个元素,但仍旧是地址,是地址就是4字节
    3.1
    p为字符首元素地址,解引用得到首元素,类型是char,故大小为1字节
    4.1
    p[0]可以写成*(p+0),也就是数组第一个元素,类型是char,大小是1字节
    5.4
    &p是字符指针的地址,是地址大小就为4字节
    6.4
    &p是地址的地址,当地址进行±运算时,与指针类型有关,&p的类型为char**,+1会跳过一个char*类型的,但仍旧是地址,为4字节
    7.4
    &p[0]为首元素地址,类型是字符指针,+1会跳过一个字节,但仍旧是地址,为4字节
    一一一一一一一一一分割线一一一一一一一一一一
    第七组:

    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.6
    p为字符串的首元素地址,传入strlen中得到6
    2.5
    p为字符串首元素地址,当地址进行±运算时,与指针类型有关,字符指针会跳过一个字节指向b,将b的地址传入strlen中得到5
    3.err
    p为字符首元素地址,解引用得到首元素,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
    4.err
    p[0]为字符a,会将字符a的ASCII码值当做地址传入strlen,由于此地址为野指针,故会error
    5.随机值
    &p得到的是字符指针的地址,由于不知道何时出现\0,故为随机值
    6.随机值
    &p是地址的地址,当地址进行±运算时,与指针类型有关,&p的类型为char**,+1会跳过一个char*类型的,由于不知道何时出现\0,故为随机值
    7.5
    &p[0]为首元素地址,类型是字符指针,+1会跳过一个字节,故得到5

    二维数组:

    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

    开始之前要明确几个概念:
    二维数组是数组的数组
    每一行的数组名是a[0],a[1],a[2]
    在这里插入图片描述

    答案:
    1.48
    a是二维数组的数组名,在sizeof中表示整个数组,那么得到的结果就是整个数组的大小,为48字节
    2.4
    a[0][0]为第一个元素,类型是int,故大小为4字节
    3.16
    a[0]是第一行的数组名,数组名放在sizeof中就代表第一行整个数组,为16字节
    4.4
    a[0]是第一行数组名,他不在sizeof中,也没有取地址,故为第一行首元素地址,当地址进行±运算时,与指针类型有关,+1后指向第一行第二个元素,但依旧为地址,那就是4字节
    5.4
    a[0]+1为第一行第二个元素地址,解引用后成为int类型的元素,故为4字节
    6.4
    a不在sizeof中,也没有取地址,故为首元素地址,二维数组的首元素地址为第一行数组的地址,类型为int(*)[4],+1跳过一个4字节的数组,指向第二行数组,但依旧是地址,故为4字节大小
    7.16

    此题有两种方法:
    1.a+1为第二行数组的地址,解引用后就是整个第二行数组,则sizeof后就是第二行整个数组的大小,为16字节
    2.*(a+1)就是a[1],a[1]就是第二行的数组名,放在sizeof中就是求第二行整个数组的大小,为16字节

    8.4
    &a[0]是第一行数组的地址,+1后就是第二行数组的地址,是地址的话就是4字节
    9.16
    解引用第二行数组地址找到的就是第二行整个数组,sizeof后就是16字节
    10.16
    a不在sizeof中,也没有取地址,故为首元素地址,即为第一行数组地址,解引用就是整个第一行数组,大小为16字节
    11.16
    sizeof是操作符,不会执行,故也不会越界,在编译时就会算出结果

    欢迎讨论与纠错,下篇也是笔试题,但是不是关于sizeof与strlen,而是会更灵活的运用

  • 相关阅读:
    金仓数据库KingbaseES客户端应用参考手册--14. sys_receivewal
    oracle 解锁表
    在使用lac时macos错误NameError: name 'libpaddle' is not defined
    金仓数据库 KingbaseGIS 使用手册(6.2. 管理函数)
    基于STM32F103ZET6库函数按键输入实验
    数据结构之单链表和双链表(封装常用方法以及实例)添加元素方法,查找元素方法,删除元素方法等等
    安装新操作系统需要注意的问题
    flink学习之sql-client之踩坑记录
    介绍:C语言—atoi函数
    WPF XAML介绍
  • 原文地址:https://blog.csdn.net/2301_78636079/article/details/132890875