指针和数组笔试题解析(最详细解析,没有之一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 指针和数组笔试题解析(最详细解析,没有之一)

前言

指针和数组在许多编程场景中经常结合使用,比如通过指针来访问数组的元素、通过指针来遍历数组等。指针和数组的灵活应用可以帮助我们更好地处理和操作数据,提高程序的性能和效率,指针和数组在C语言中具有重要的地位和作用,它们是程序设计中不可或缺的重要概念。本文将详细解析指针和数组相关笔试题!!

1. 一维数组和指针相关笔试题

题目及解析:

int main()
{
  int a[] = { 1,2,3,4 };

  printf("%d\n", sizeof(a));  //数组名单独放在sizeof内部,这里a表示整个数组,计算的是整个数组,为16(4*4)个字节
  printf("%d\n", sizeof(a + 0));//a表示首元素的地址,a+0还是表示首元素地址,是地址就是4/8个字节
  printf("%d\n", sizeof(*a)); //a表示首元素地址,*a表示首元素,大小为4个字节
  printf("%d\n", sizeof(a + 1));//a表示首元素地址,arr+1跳过一个整型长度指向第二个元素(2)的地址,是地址大小就是4/8个字节
  printf("%d\n", sizeof(a[1]));//a[1]取出的是第二个元素2,为int类型,大小为4个字节
  printf("%d\n", sizeof(&a)); //&a取出的是整个数组的地址,但只要是地址,大小都是4/8个字节

  printf("%d\n", sizeof(*&a));  
  //解读一:sizeof(*&a) ---> sizeof(a) ---> 同第一个为16字节
  //解读二:由于我们熟知对整型指针进行解引用得到的是整型;对字符指针进行接引用得到的是一个字符
  //      这里&a表示数组指针,类型为int (*)[4],对它进行解引用操作得到的是一个数组,即*&a表示整个数组,大小为4*4即16个字节

  printf("%d\n", sizeof(&a + 1));
  //&a取出的是整个数组,&a+1跳过整个数组,指向的是第四个元素4的下一个元素的地址
  //但是地址大小就是4/8个字节

  printf("%d\n", sizeof(&a[0]));//&a[0]取出的是第一个元素1的地址,大小为4/8个字节
  printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1表示取出首元素地址后向后移动一个整型字长,指向第二个元素2的地址,为4/8个字节

  return 0;
}

x64环境下运行结果:

2. 字符数组和指针相关笔试题

2.1 题型一:

题目及解析:

int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  
  printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节
  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));//第二个元素的地址,是4/8个字节
  return 0;
}

x64环境下运行结果:

2.2 题型二:

题目及解析:

int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结果就是随机值
  printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值

  //printf("%d\n", strlen(*arr));//err, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97
  //strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ascii码值是97,那就是将97作为地址传参
  //strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了
  //printf("%d\n", strlen(arr[1]));//err

  printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的
                 //那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计,结果为随机值

  printf("%d\n", strlen(&arr + 1));//&arr+1,跳过整个数组,结果为随机值
  printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,结果为随机值
  return 0;
}

x64环境下运行结果:

2.3 题型三:

题目及解析:

int main()
{
  char arr[] = "abcdef";//[a b c d e f \0]
  printf("%d\n", sizeof(arr));//数组中共有7个元素,结果为7

  printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址,结果为4/8
  printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节
  //*arr--> *(arr+0) -- arr[0]

  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
  return 0;
}

x64环境下运行结果:

2.4 题型四:

题目及解析:

int main()
{
  char arr[] = "abcdef";//[a b c d e f \0]

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

  //printf("%d\n", strlen(*arr));//err,传的是首元素a
  //printf("%d\n", strlen(arr[1]));//err,传的是第二个元素b
  //strlen需要传过去的是指针,如果传字符会造成非法访问内存,报错

  printf("%d\n", strlen(&arr));//6
  printf("%d\n", strlen(&arr + 1));//&arr+1跳过整个数组,导致数组后面\0没有明确位置,导致结果为随机值
  printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始向后访问,结果为5
  return 0;
}

x64环境下运行结果:

3. 指针和字符串相关面试题

3.1 题型一:

题目及解析:

int main()
{
  char* p = "abcdef";
  
  printf("%d\n", sizeof(p));//p是一个指针变量,大小就是4/8个字节
  printf("%d\n", sizeof(p + 1));//p+1是'b'的地址,是地址大小就是4/8个字节
  
  printf("%d\n", sizeof(*p));//*p 就是'a',就是1个字节
  printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) --> *p ,大小为1个字节

  printf("%d\n", sizeof(&p));//&p -- char**,二级指针也是指针大小为4/8个字节
  printf("%d\n", sizeof(&p + 1));//*p+1本质上还是一个指针,大小为4/8个字节
  printf("%d\n", sizeof(&p[0] + 1));//4/8 , &p[0] + 1得到是'b'的地址 

  return 0;
}

x64环境下运行结果:

3.2 题型二:

**题目及解析:

//由于原理和上面完全一样,所以在此就不再累赘了
int main()
{
  char* p = "abcdef";

  printf("%d\n", strlen(p));//6
  printf("%d\n", strlen(p + 1));//5
  //printf("%d\n", strlen(*p));//err
  //printf("%d\n", strlen(p[0]));//err
  printf("%d\n", strlen(&p));//随机值
  printf("%d\n", strlen(&p + 1));//随机值
  printf("%d\n", strlen(&p[0] + 1));//5
  return 0;
}

x64环境下运行结果:

4. 二位数组和指针相关面试题

**题目及解析:

int main()
{
  int a[3][4] = { 0 };

  printf("%d\n", sizeof(a));//sizeof(数组名)不管是一维数组还是二维数组都是表示整个数组,结果为3*4*4 = 48
  printf("%d\n", sizeof(a[0][0]));//大小为4

  printf("%d\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名
  //数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节

  printf("%d\n", sizeof(a[0] + 1));
  //a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&
  //a[0]表示数组首元素的地址,也就是a[0][0]的地址
  //所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
  //
  printf("%d\n", sizeof(*(a[0] + 1)));//4
  //计算的是就是第一行第2个元素的大小

  printf("%d\n", sizeof(a + 1));//4 / 8
  //a是数组首元素的地址,是第一行的地址 int(*)[4]
  //a+1 就是第二行的地址

  printf("%d\n", sizeof(*(a + 1)));//16
  //*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小
  //a+1 --> 是第二行的地址,int(*)[4]
  //*(a+1) 访问的第二行的数组

  printf("%d\n", sizeof(&a[0] + 1));//4/8
  //&a[0]是第一行的地址 int(*)[4]
  //&a[0]+1 是第二行的地址 int(*)[4]

  printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小

  printf("%d\n", sizeof(*a));//计算的是第一行的大小-16
  //a是数组首元素的地址,就是第一行的地址
  //*a 就是第一行
  //*a --> *(a+0) --> a[0]

  printf("%d\n", sizeof(a[3]));//16
  //sizeof在计算其大小时,其背后原理是sizeof操作符只关心其类型,根据类型来计算大小
  //并不会真正的访问内存,所以在此所谓的数组越界对sizeof计算其大小并没有太大关系
  return 0;
}

x64环境下运行结果:

5. 总结

1. sizeof(数组名),这里的数组表示的是整个数组,不管是一维数组还是二维数组计算的都是整个数组的大小。

2. &数组名,这里的数组名表示的也是整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名表示的都是首元素的地址。

4. sizeof计算大小时,其工作原理是根据其类型来判断的,并不会真正访问内存来计算大小。所以在计算数组大小过程中,即使出现数组越界,但对sizeof来说没有影响,依然可以计算其大小。

6. 结尾

本篇文章到此就结束了。创作不易,如果对你有帮助记得点赞加收藏哦。感谢您的支持!!


相关文章
|
14天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
30 3
|
13天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
27 2
|
22天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
27 1
|
1月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
1月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
1月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
18 0

推荐镜像

更多