【C生万物】 指针和数组笔试题汇总 (下)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 【C生万物】 指针和数组笔试题汇总 (下)

前言:

承接上文,继续进行指针和数组的练习。


Part2:指针笔试题


1.做题


均要求输出结果


笔试1


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

答案及解析:

93222b1de89b5ee2290ba99b1384ea5d_9dcecf3493f8458a899e95ed578e2acc.png

*(a + 1): a表示首元素地址,+1得到第二个元素地址,解引用后得到 2
*(ptr - 1): ptr记录了整个数组下一位的地址,-1后得到数组最后一个元素的地址,解引用后得到5


笔试2


struct Test
{
  int Num;
  char* pcName;
  short sDate;
  char cha[2];
  short sBa[4];
}*p;
//假设p的值为0x00100000。 如下表表达式的值分别为多少?
//已知:结构体Test类型的变量大小是20个字节
int main()
{
  printf("%p\n", p + 0x1);
  printf("%p\n", (unsigned long)p + 0x1);
  printf("%p\n", (unsigned int*)p + 0x1);
  return 0;
}


答案及解析:


0x00100014
0x00100001
0x00100004
0x开头,表示十六进制
p + 0x1                    -- p是结构体指针,+1表示加一个结构体的大小(20) 
   0x00100000 
 + 0x00000014 
== 0x00100014
(unsigned long)p + 0x1)    -- p强转为无符号长整型,+1就是+1
   0x00100000 
 + 0x00000001 
== 0x00100001
(unsigned int*)p + 0x1)    -- p强转为整型指针,+1表示跳过一个整型
   0x00100000 
 + 0x00000004 
== 0x00100004


笔试3


// 小端  x86环境
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0;
}


答案及解析:

1. %x 表示以十六进制打印
2. 0x4
3. 0x02000000
int *ptr1 = (int *)(&a + 1);
ptr1[-1]: 即*(ptr1 - 1),&a + 1表示整个数组的下一个位置,强转为整型指针后-1,表示向前跳过一个整型,即数组最后一个元素
int *ptr2 = (int *)((int)a + 1);
*ptr2:

f3467d9d50fd718cecc85db18305afe8_58c7b261726f4628a09589fb2c2df9ee.png

笔试4


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

答案及解析:

b9858855f4001ad75ca37121fc8a9d74_6583b88612594502b5b09c23671f6703.png

注意逗号表达式,括号内取最后一个值
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
即{1,3,5}
理解: 
 1  3
 5  0
 0  0
a[0] 表示1的地址
p[0] 相当于*(p+0),即1


笔试5


int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

答案及解析:


8aac231cc556e7d5b9a00eb04db1f218_e673c9e5eff5402d94d351bf9b527986.png


a 是二维数组名,p 是数组指针


p 与 a 指向的首元素相同


下图解释了两者的意义:


c30e4e87c1a2faf42d6c977dbe10b4f6_fc83e1b1145341f399ce77c904667b22.png


由此可以计算出 &p[4][2] - &a[4][2] 的值为 -4 ,按照整型打印就是 -4


按照地址打印,先要看 -4 在内存中是如何存储的:


即 -4 的补码形式:


11111111 11111111 11111111 11111100


换算为十六进制:


FFFFFFFC


笔试6


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

答案及解析:


4dd9b383682102c9eb47c759a637c8a3_2a4bdf7f6e9d40af89ae3025344d2c8b.png


1 2 3 4 5
6 7 8 9 10
int* ptr1 = (int*)(&aa + 1);    即10的下一个位置的地址
int* ptr2 = (int*)(*(aa + 1));  aa+1表示第二行的地址,解引用得到第二行数组
*(ptr1 - 1)        向前跳过一个整型,即二维数组的最后一个元素10
*(ptr2 - 1)        第二行数组向前跳过一个整型,得到第一行数组的最后一个元素5


笔试7


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

答案及解析:


cd2a242175d66a32696f98dd9eaa27d5_976763566c2d4b17903c25e3963808c5.png

1da2341e1f942d8ad48c6f9180754ea9_c5340516c18e45bc87f914ee5e106ebc.png


a 是一个存贮字符指针的数组,里面有三个元素,分别指向三个字符串的首字母;


pa 是指针,它指向的数据类型是字符指针;


pa 指向第一个元素 char* a[0];


pa++,跳转到char* a[1],解引用就得到了字符串 at


笔试8


int main()
{
  char* c[] = { "ENTER","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;
}


答案及解析:

a2dfa50cf9d9b49225df55a25b88e975_3df68221f934479eb5e6992cfca51532.png


这是原始状态:

8d3e30756d857ab819f0da5bb4e14d93_f121a3e14e624b6d8c5b8bcaa3697ecc.png



**++cpp:

优先级 ** < ++


cpp++,指向空间c+2 ,一次解引用后得到空间 c+2 ,再次解引用得到 char*[2],指向P,打印出POINT;(cpp已被改变,指向空间c+2)


*-- * ++cpp + 3

先自cpp向左操作,最后+3


cpp++,此时已指向空间c + 1 ,解引用后得到空间c+1,此时--,即空间c+1--,得到空间c,解引用后得到ENTER中第一个E的地址,最后+3,得到ENTER中第二个E的地址,打印出ER;(cpp又被改变,指向空间c + 1 )


*cpp[-2] + 3  即 **(cpp-2) + 3

cpp++,指向空间c + 3,两次解引用得到FIRST中的F的地址,+3,得到其中S的地址,打印出ST;  (cpp又被改变,指向空间c + 3 )


cpp[-1][-1] + 1   即 *(*(cpp-1)-1) + 1

cpp-1后解引用,得到空间c+2,-1得到空间c+1,解引用得到NEW中N的地址,+1得到E的地址,打印出EW。


2.总结


指针+1表示跳过一个类型大小


如:整型指针+1,表示跳过一个整型的大小


一维数组名 a

a表示首元素地址,+1表示第二个元素的地址

&a表示整个数组的地址,+1表示数组末端的地址(数组外)


二维数组名aa

aa表示二维数组中一行数组的地址,+1跳过一行

aa[i] 表示二维数组中第 i 行的地址,+1跳过一行

&aa表示整个二维数组的地址,+1表示二维数组的末端(数组外)


向%s传递字符地址,从当前字符开始,打印到 \0 结束  


总结:

带你做了8道笔试题,有梯度,会第8道,这一部分就掌握的很好了。


码文不易

如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦  💗💗


目录
相关文章
|
15天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
30 3
|
14天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
27 2
|
23天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
28 1
|
1月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
1月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
1月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
1月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
18 0
|
1月前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
|
3月前
|
搜索推荐 C语言
指针与数组
指针与数组
58 9