【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !

简介: 【数组和进阶指针经典笔试题12道】这些题,满足你对数组和指针的所有幻想,come on !

近几年互联网受疫情影响,许多互联网都使用牛客网在线笔试招人


很多同学因为不熟悉牛客网的环境和使用,最后在线笔试面试中屡屡受挫


牛客网提供了语言巩固,算法提高等在线OJ题,更有面试真题,大厂内推!


链接附上点击链接注册牛客网


牛客网这么好用,但是下面几个关于牛客网的知识你了解过吗?


你知道你OJ过不了,牛客网几种经典的英文报错提示的含义吗?

你知道牛客网的OJ分为IO型和接口型吗?

你使用过牛客网的调试功能吗?

众所周知,指针是C语言的灵魂,很多人就是倒在指针的脚下。今天,我来带大家看一看指针在笔试中是怎么考的吧!(提示:本篇博客测试环境是vs-x64,该环境下指针占8个字节)


练习题1

int main()
{
  int a[4] = { 1,2,3,4 };
  printf("%u\n", sizeof(a));//16-sizeof(数组名)-整个数组
  printf("%u\n", sizeof(a+0));//8-不是单独的数组名-数组首元素的地址
  printf("%u\n", sizeof(*a));//4-数组首元素的地址解引用-数组首元素
  printf("%u\n", sizeof(a+1));//8-数组第2个元素的地址
  printf("%u\n", sizeof(a[1]));//4-数组第2个元素
  printf("%u\n", sizeof(&a));//8-整个数组的地址
  printf("%u\n", sizeof(*&a));//16-对整个数组的地址解引用,得到的是整个数组-sizeof(数组名)
  printf("%u\n", sizeof(&a+1));//8-&a是整个数组的地址,+1跳过一个数组,还是一个数组的地址
  printf("%u\n", sizeof(&a[0]));//8-首元素的地址
  printf("%u\n", sizeof(&a[0]+1));//8-第2个元素的地址
  return 0;
}

232451e451e74c8daa22895bd48f860d.png


练习题2

int main()
{
  char str[5] = { 'a','b','c','d','e' };
  printf("%d\n", sizeof(str));//5-sizeof(数组名)-整个数组
  printf("%d\n", sizeof(str+0));//8-数组首元素的地址
  printf("%d\n", sizeof(*str));//1-数组首元素
  printf("%d\n", sizeof(str[1]));//1-数组第二个元素
  printf("%d\n", sizeof(&str));//8
  printf("%d\n", sizeof(&str[0]+1));//8
  printf("%d\n", sizeof(str[0]+1));//4-字符和整型相加-整型提升
  //等价于printf("%d\n", sizeof('a'+1));//4-整型提升
  return 0;
}

练习题3

int main()
{
  char str[] = { 'a','b','c','d','e' };
  printf("%d\n", strlen(str));//随机值
  printf("%d\n", strlen(str+0));//随机值
  printf("%d\n", strlen(*str));//strlen('a')-->strlen(97);//野指针
  printf("%d\n", strlen(str[1]));//野指针
  printf("%d\n", strlen(&str));//随机值
  printf("%d\n", strlen(&str+1));//随机值
  printf("%d\n", strlen(&str[0]+1));//随机值
  return 0;
}

这里的第三个printf处如果调试的话,这个错误代表的意思就是访问了非法内存(有一些内存地址是没有办法访问的,有一些是允许访问,但是也会进行一定的检测)


de0b848b14e84898af640333d16dc61b.png


关于sizeof和strlen:


strlen是求字符串长度的,关注的是字符串中的'\0',计算的是\0之前出现字符的个数


strlen是库函数,只针对字符串


sizeof只关注占用内存的大小,不在乎内存中放的是什么


sizeof是操作符


练习题4

int main()
{
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//3*4*4=48-整个二维数组
  printf("%d\n", sizeof(a[0]));//8错//4*4=16对 sizeof(一维数组数组名)-整个第一个一维数组
  printf("%d\n", sizeof(a[0]+1));//8-第2个一维数组的地址
  printf("%d\n", sizeof(a[0][0]));//4-第一个一维数组的第1个元素
  printf("%d\n", sizeof(*(a[0]+1)));//4-第一个一维数组的第2个元素
  printf("%d\n", sizeof(*(a+1)));//8错//4*4=16对 sizeof(一维数组数组名)-整个第2个一维数组
  printf("%d\n", sizeof(a+1));//8-第2个一维数组的地址
  printf("%d\n", sizeof(&a[0]+1));//8-第一个一维数组的第2个元素
  printf("%d\n", sizeof(*a));//4*4=16-整个第一个一维数组
  printf("%d\n", sizeof(a[3]));//16-整个第四个一维数组
  return 0;
}

ea3a7d2a47e94d21b33fd4609596e49e.png


练习题5


int main()
{
  int a[5] = { 1,2,3,4,5 };
  int* ptr = (int*)(&a + 1);
  printf("%d %d", *(a + 1), *(ptr - 1));//2 5
  return 0;
}

b5f06e34c18e4a52bb6bf0ec2d188871.png


练习题6

struct Test
{
  int num1;
  char* num2;
  short num3;
  char num4[2];
  short num5[4];
}*p;
//假设p的值为0x100000,如下表达式的值分别是多少?
//已知在当前环境下,Test类型的变量大小是20个字节
//考察:指针/整数+1到底是加了多少
int main()
{
  printf("%p\n", p + 0x1);//0x100014
  printf("%p\n", (unsigned long)p + 0x1);//0x100001
  printf("%p\n", (unsigned int*)p + 0x1);//0x100004
  return 0;
}

0x1就是十六进制的1,也就是十进制的1:


对于第一个p+0x1中p是struct Test* 类型的指针,加1,跳过一个sizeof(struct Test)==20,也就是0x00014大小。


同理第二个p是被强制转换为了unsigned long类型,是一个整数,整数=1就是+1,然后按照%p打印出来,加的因为就是1(没有超过16),所以和在原来的0x10000上加1是一样的。


同理第三个p是被强制转换为了unsigned int*类型,加1,加的是4个字节。


练习题7

int main()
{
  int a[4] = { 1,2,3,4 };
  int* ptr1 = (int*)(&a + 1);
  int* ptr2 = (int*)(a + 1);
  int* ptr3 = (int*)((int)a + 1);
  int* ptr4 = (int*)((char*)a + 1);
  printf("%x %x %x %x\n\n", ptr1[-1], *ptr2,*ptr3,*ptr4);//
  return 0;
}

4c46a6edb63647a680655243df739b55.png

ptr3得到的方式是:

通过将整型指针强制转换为整型数值,然后加1,最后再强制转换为整型指针;

ptr4得到的方式是:

通过将整型指针强制转换为字符指针,然后加1,最后再强制转换为整型指针。

两个的效果是一样的。


8189041e8dad4a37a4b0275854892e9d.png


练习题8


int main()
{
  int a[3][2] = { (0,1),(2,3),(3,4) };//坑点:逗号表达式
  int* p;
  p = a[0];
  printf("%d\n", p[0]);
  //等价于printf("%d\n", *p);
  return 0;
}


image.png

image.png

练习题9

int main()
{
  int a[4][5];
  int(*p)[3];//重点在于这里的3,不是5
  p = a;
  printf("%p %d\n", &p[3][2] - &a[3][2], &p[3][2] - &a[3][2]);
  return 0;
}

7c2873f684734dce97c0fa5dac16347e.png

fd60fd2b401b4b0fafd61ef9ce827c22.png

aeaef388fff84272941b26f9b653c25b.png


练习10

int main()
{
  int a[2][5] = { 1,2,3,4,5,6,7,8,9,10 };
  int* ptr1 = (int*)(&a + 1);
  int* ptr2 = (*(a + 1));
  //等价于int* ptr2 = (int*)(a + 1);
  printf("%d %d\n", *(ptr1 - 1), *(ptr2 - 1));//10 5
  return 0;
}

245da5cdc95c4d8eaa5ac1832995ef65.png

218494cf3cb64adf9ff0931ec565ba11.png


练习11

int main()
{
  char* a[] = { "I will work","at","alibaba" };
  char** pa = a;
  pa++;
  printf("%s\n", *pa);
  return 0;
}

a4c411b03e2b4372a7cee017ff1c476e.png

f0251ec56a734e998dbb953adf05ae1d.png


练习题12

int main()
{
  char* c[] = { "ENTRE","NEW","POINT","FIRST" };
  char** cp[] = { c + 3,c + 2,c + 1,c };
  char*** cpp = cp;
  printf("%s\n", **++cpp);
  printf("%s\n", *--*++cpp+3);
  printf("%s\n", *cpp[-2]+3);
  printf("%s\n", cpp[-1][-1]+1);
  return 0;
}

下面是我自己的理解方式:


[]和*都可以过桥(也就是找到指针所指向的那个目标), cpp[-1]就是指向的*(cpp-1),就是先指针-1(指向发生改变),然后过桥(找到指针指向的那个目标);


然后这里的虚线就是不会有自增++有副作用


a=a+1;有副作用(a变了)


但是a+1;就没有副作用(a没有变


4d303d9bda204aff88d2dc47d27b5853.png

1de501f1747c4c78b5a6ae9e89d43ccc.png

33026e9a368342cfbd056f49feafb74b.png

image.png


image.png


目录
相关文章
|
13天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
30 3
|
13天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
26 2
|
21天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
26 1
|
1月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
1月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
22 0
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
3月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)