【C 高阶】- 数组和指针笔试题精选

C 高阶系列导航


1. 前言

在 C/C++ 相关的岗位笔试中,数组和指针相关的知识点为高频考点,能够很好考察应聘者的 C/C++ 功底。因此,本文精选了数组与指针相关的笔试题,并解析解题思路,希望能够加强读者对数组和指针的理解。

在阅读本文前,强烈推荐先学习博文《【C 高阶】- 彻底理解数组与指针》,里面详细介绍了数组与指针之间的共性与关联。


2. 笔试题精选

第一题

以下程序输出的结果是?

int nums[5] = {1, 2, 3, 4, 5};
int* p = (int*)(&nums + 1);
printf("*(nums + 1) = %d\n", *(nums + 1)); 
printf("*(p - 1) = %d\n", *(p - 1));    
  • 解析
  1. &nums + 1 等价于 (size_t)&nums + 1 * sizeof(int[5]),此时 p 指向了数组 nums 的下一个地址。即假设 nums 的地址为 0x10000000,则 p 指向的地址为 0x10000014。
  2. nums + 1 等价于 (size_t)nums + 1 * sizeof(int),返回的 nums[1] 的地址。
  3. p - 1 等价于 (size_t)p - 1 * sizeof(int),返回指针 p 所指地址向前偏移 4 个字节后的地址。由于 p 指向了数组 nums 的下一个地址,因此 p - 1 得到的是 nums[4] 的地址。
  • 输出结果
*(nums + 1) = 2
*(p - 1) = 5

第二题

以下程序输出的结果是?

int* p = NULL;
printf("p = %p\n", p); 
printf("p + 1 = %p\n", p + 1); 
printf("(size_t)p  + 1 = %lu\n", (size_t)p  + 1);
printf("(short*)p  + 1 = %p\n", (short*)p  + 1);
printf("(long*)p  + 1 = %p\n", (long*)p  + 1);
  • 解析
  1. p + 1 等价于 (size_t)p + 1 * sizeof(int),返回指针 p 所指地址偏移 4 个字节后的地址。
  2. (size_t)p + 1p 所指的地址值直接加一。
  3. (short*)p + 1 等价于 (size_t)(short*)p + 1 * sizeof(short),返回指针 p 所指地址向后偏移 2 个字节后的地址。
  4. (long*)p + 1 等价于 (size_t)(long*)p + 1 * sizeof(long),返回指针 p 所指地址向后偏移 8 个字节后的地址。
  • 输出结果
p = 0x0
p + 1 = 0x4
(size_t)p  + 1 = 1
(short*)p  + 1 = 0x2
(long*)p  + 1 = 0x8

第三题

现有指针 p,指针地址 &p 为 0x10000000。以下程序输出的结果是?

printf("&p + 1 = %p\n", &p + 1); 
printf("(long)&p  + 1 = %p\n", (void*)((long)&p  + 1));
printf("(short*)&p  + 1 = %p\n", (short*)&p  + 1);
printf("(long*)&p  + 1 = %p\n", (long*)&p  + 1);
printf("(int**)&p  + 1 = %p\n", (int**)&p  + 1);
  • 解析
  1. &p + 1 等价于 (size_t)&p + 1 * sizeof(int*),返回指针 p 的地址偏移 8 个字节后的地址。
  2. (long)&p + 1p 的地址值直接加一。
  3. (short*)&p + 1 等价于 (size_t)(short*)&p + 1 * sizeof(short),返回指针 p 的地址向后偏移 2 个字节后的地址。
  4. (long*)&p + 1 等价于 (size_t)(long*)&p + 1 * sizeof(long),返回指针 p 的地址向后偏移 8 个字节后的地址。
  5. (int**)&p + 1 等价于 (size_t)(int**)&p + 1 * sizeof(int*),返回指针 p 的地址向后偏移 8 个字节后的地址。
  • 输出结果
&p + 1 = 0x10000008
(long)&p  + 1 = 0x10000001
(short*)&p  + 1 = 0x10000002
(long*)&p  + 1 = 0x10000008
(int**)&p  + 1 = 0x10000008

第四题

现有数组 nums、指针 p1p2,指针地址 &p 为 0x10000000。已知以下程序为小端存储策略,则输出的结果是?

int nums[] = {1, 2, 3, 4};
int* p1 = (int*)(&nums + 1);
int* p2 = (int*)((size_t)nums + 1);
printf("p1[-1] = %d\n", p1[-1]);
printf("*p2 = 0x%x\n", *p2);
  • 解析
  1. &nums + 1 等价于 (size_t)&nums + 1 * sizeof(int[4]),此时 p1 指向了数组 nums 的下一个地址。即假设 nums 的地址为 0x10000000,则 p1 指向的地址为 0x10000010。
  2. (size_t)nums + 1nums 表示的地址值直接加一,此时 p2 指向了数组 nums 表示的地址的下一个地址。即假设 nums 的地址为 0x10000000,则 p2 指向的地址为 0x10000001。
  3. p1[-1] 等价于 *((size_t)p1 - 1 * sizeof(int)),而 (size_t)p1 - 1 * sizeof(int) 返回指针 p1 所指地址向前偏移 4 个字节后的地址,即 nums[3] 的地址。
  4. 由于 p2 指向了数组 nums 表示的地址的下一个地址,即 *p 从该地址开始取 4 字节地址内存按整型解析,因此需要分析数组 nums 在内存中的存储情况。由于程序为小端存储策略,因此具体内存分布如下所示。可见,*p2 从所指地址开始解析的 4 字节内存为 0x02000000。
地址:低 ->|  nums[0]  |  nums[1]  |  nums[2]  |  nums[3]  |    
nums: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
         |
         p2
  • 输出结果
p1[-1] = 4
*p2 = 0x2000000

第五题

以下程序输出的结果是?

int nums[5][5] = {0};
int (*p)[3] = (int(*)[3])nums;
printf("&p[3][2] - &nums[3][2] = %d\n", (int)(&p[3][2] - &nums[3][2]));
  • 解析
  1. nums 为有 5 个子数组、每个子数组有 5 个元素的二维数组,因此 nums 实际有 25 个整型元素。
  2. p 为数组指针,所属的数组类型为 3 个元素。
  3. &p[3][2] 等效于 ((int[3])((size_t)p + 3 * sizeof(int[3])))[2] (非标准写法),即返回 p 所指地址向后偏移 11 个字节后的地址。
  4. &nums[3][2] 返回 nums 中第 17 个元素的地址。
  • 输出结果
&p[4][2] - &nums[4][2] = -6

第六题

以下程序输出的结果是?

int nums[2][4] = {1, 2, 3, 4, 5, 6, 7, 8};
int* p1 = (int *)(&nums + 1);
int* p2 = (int *)(*(nums + 1));
printf("*(p1 - 1) = %d\n", *(p1 - 1));
printf("*p2 = %d\n", *p2);
  • 解析
  1. &nums + 1 等价于 (size_t)&nums + 1 * sizeof(int[2][4]),此时 p1 指向了数组 nums 的下一个地址。即假设 nums 的地址为 0x10000000,则 p1 指向的地址为 0x10000020。
  2. nums + 1 等价于 (int[4])((size_t)nums + 1 * sizeof(int[4])) (非标准写法),返回 nums 的地址向后偏移 16 个字节后的地址,即 p2 指向了 nums[4]
  3. p - 1 等价于 (size_t)p - 1 * sizeof(int),返回指针 p 所指地址向前偏移 4 个字节后的地址。由于 p 指向了数组 nums 的下一个地址,因此 p - 1 得到的是 nums[1][3] 的地址。
  • 输出结果
*(p1 - 1) = 8
*p2 = 5

第七题

以下程序输出的结果是?

char* str[] = {"HELLO", "WORLD"};
char** p = str;
printf("*p = %s\n", *p);
printf("p[1] = %s\n", p[1]);
printf("p[0] + 1 = %s\n", p[0] + 1);
  • 解析
  1. str[1] 指向 "WORLD"str[0] 指向 "HELLO"
  2. p 指向 strp = &str[0]*p <-> str[0]
  3. p[1] 等价于 *((char**)((size_t)p + 1 * sizeof(char*))),返回 p 所指地址 &str[0] 向前偏移 8 个字节后的地址 &str[1] 上的内容 str[1]
  4. p[0] 等价于 *((char**)((size_t)p + 0 * sizeof(char*))),返回 p 所指地址 &str[0] 上的内容 str[0]str[0] + 1 等价于 (size_t)str[0] + 1 * sizeof(char),返回 str[0] 所指地址向前偏移 1 字节后的地址。
  • 输出结果
*p = HELLO
p[1] = WORLD
p[0] + 1 = ELLO

第八题

以下程序输出的结果是?

char* str[] = {"HELLO", "WORLD"};
char** p1[] = {str + 1, str};
char*** p2 = p1;
printf("**++p2 = %s\n", **++p2);
printf("*++*p2 + 1 = %s\n", *++*p2 + 1);
printf("*p2[-1] + 3 = %s\n", *p2[-1] + 3);
printf("p2[-1][-1] + 1 = %s\n", p2[-1][-1] + 1);
  • 解析
  1. p1[0] 指向 str[1]str[1] 指向 "WORLD"p1[1] 指向 str[0]str[0] 指向 "HELLO"
  2. p2 指向了 p1p2 = &p1[0]*p2 <-> p1[0] 指向了 str[1]**p2 <-> *p1[0] <-> str[1] 指向了 "WORLD"
  3. **++p2p2 先与“++”结合得 p2 = p2 + 1 = (char***)((size_t)p2 + 1 * sizeof(char**)),此时 p2 所含地址值为地址 &p1[0] 向后偏移 8 个字节后的地址 &p1[1]*p2 <-> p[1] 指向了 str[0]**p2 <-> *p[1] <-> str[0] 指向了 "HELLO"
  4. *++*p2 + 1p2 先与*结合为 *p2 <-> p[1],可得 *++(p1[1])p1[1] 先与“++”结合为 p1[1] = p1[1] + 1 = (char**)((size_t)p1[1] + 1 * sizeof(char*)),此时 p1[1] 所含地址值为地址 &str[0] 向后偏移 8 个字节后的地址 &str[1]*p1[1] <-> str[1]str[1] + 1 等价于 (size_t)str[1] + 1 * siezof(char),返回 str[1] 所指地址向后偏移 1 个字节后的地址。
  5. *p2[-1]p2 先与“[]”结合,p2[-1] 等价于 *((char***)((size_t)p2 - 1 * sizeof(char**))),返回 p2 所含地址值 &p1[1] 向前偏移 8 个字节后的地址 &p[0] 上的内容即 p1[0]*p2[-1] <-> *p1[0] <-> str[1]str[1] + 3 等价于 (size_t)str[1] + 3 * sizeof(char),返回 str[1] 所指地址向后偏移 3 个字节后的地址。
  6. p2[-1][-1],经上分析可知 p2[-1] <-> p1[0](p1[0])[-1] 等价于 *((char**)((size_t)p1[0] - 1 * sizeof(char*))),则返回 p1[0] 所指地址 &str[1] 向前偏移 8 个字节后的地址 &str[0] 上的内容即 str[0]str[0] + 1 等价于 (size_t)str[0] + 1 * sizeof(char),返回 str[0] 所指地址向前偏移 1 个字节后的地址。
  • 输出结果
**++p2 = HELLO
*++*p2 + 1 = ORLD
*p2[-1] + 3 = LD
p2[-1][-1] + 1 = ELLO
发布了60 篇原创文章 · 获赞 36 · 访问量 5917

猜你喜欢

转载自blog.csdn.net/qq_35692077/article/details/103376764