(C语言)指针运算 习题练习1.2(压轴难题)

在上一张已经练习了三道习题,小试牛刀了,那么在本章在来几题,练练手。(习题三是压轴难题)

习题一

cs 复制代码
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;
}

这里借助画图也可以更好的理解。

&aa是整个数组的地址,那么加一就是跳过整个数组,指向数组末尾之后的位置。强制转换为int*后,ptr1指向数组末尾后的地址。

看图。

欧克,那么ptr1 - 1回退一个int的位置,指向数组最后一个元素10。那么ptr1-1就指向10

所以第一个输出10.

第二个:1. aa在表达式中退化为int (*)[5](指向第一行的指针)。

2. aa + 1指向第二行的首地址(即元素6的地址)。

3.*****(aa + 1)解引用得到第二行的数组,退化为int*指向6

4.****ptr2 - 1回退一个int的位置,指向第一行的最后一个元素5,故*(ptr2 - 1)5。

所以本题的答案为 10,5

习题二

cs 复制代码
#include <stdio.h>
int main()
{
    char* a[] = { "work","at","alibaba" };
    char** pa = a;
    pa++;
    printf("%s\n", *pa);
    return 0;
}

数组名 a 在表达式中退化为 char** 类型(指向第一个元素 a[0] 的指针)。

cs 复制代码
char** pa = a; // pa 指向 a[0]

pa 的类型是 char**,指向 a 的第一个元素 a[0](即字符串 "work" 的地址)。

cs 复制代码
pa++; // pa 移动到 a[1]
  • pachar** 类型,指向 char* 元素。

  • 执行后,pa 指向数组的第二个元素 a[1](即字符串 "at" 的地址)。

cs 复制代码
printf("%s\n", *pa); // 输出 a[1] 指向的字符串
  • *pa 解引用 pa,得到 a[1] 的值(即字符串 "at" 的首地址)。

  • %s 格式输出时,会打印从该地址开始的字符串 "at"

  • 答案为 at

习题三

注意:此题为压轴题,请认真分析,一定一定要画图。
cs 复制代码
#include <stdio.h>

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

答案:

POINT
ER
ST
EW

做本题首先要画图,上图。

这是在运算前的必要流程,由此图我们可以相对容易理解。

那么接下来 SHOW TIME

一:

cs 复制代码
printf("%s\n",**++cpp);

这步先找突破口,cpp,

步骤如下:

  • ++cpp:将 cpp 增加1,使其指向 cp[1]
  • *cpp:解引用 cpp,得到 cp[1],即 c + 2
  • **cpp:解引用 *cpp,得到 *(c + 2),即 "POINT"

所以结果输出 POINT

二:

cs 复制代码
   printf("%s\n", *-- * ++cpp + 3);

做这道题之前可以将本题简化一下,简化后为 * --*++cpp +3

因此,第二个 printf 输出 "ER"

  • ++cpp:将 cpp 增加1,使其指向 cp[2]。(**PS:**在上一步已经将进行一次++cpp,所以这里初始状态就是cpp[1])
  • *cpp:解引用 cpp,得到 cp[2],即 c + 1
  • --*cpp:将 *cpp 减少1,使其指向 c,即 "ENTER"
  • *--*cpp + 3:解引用 --*cpp,得到 "ENTER",然后加上3,指向 "ENTER" 的第4个字符,即 "ER"

三:

cs 复制代码
printf("%s\n", *cpp[-2] + 3);

这里也可以进行一步简化,cpp[-2]:相当于 *(cpp-2):

  • cpp[-2]:由于 cpp 当前指向 cp[2],所以 cpp[-2] 指向 cp[0]
  • *cpp[-2]:解引用 cpp[-2],得到 cp[0],即 c + 3
  • *cpp[-2] + 3:解引用 *cpp[-2],得到 "FIRST",然后加上3,指向 "FIRST" 的第4个字符,即 "ST"

因此,第三个 printf 输出 "ST"

cs 复制代码
    printf("%s\n", cpp[-1][-1] + 1);
  • cpp[-1]:由于 cpp 当前指向 cp[2],所以 cpp[-1] 指向 cp[1]
  • cpp[-1][-1]:解引用 cpp[-1],得到 cp[1],即 c + 2,然后解引用 -1,得到 *(c + 1),即 "NEW"
  • cpp[-1][-1] + 1:解引用 cpp[-1][-1],得到 "NEW",然后加上1,指向 "NEW" 的第2个字符,即 "EW"

因此,第四个 printf 输出 "EW"

欧克 指针运算的习题就到这里了,大家可以在独立运算一下,更好的理解。

相关推荐
一个public的class1 小时前
什么是 Java 泛型
java·开发语言·后端
士别三日&&当刮目相看1 小时前
JAVA学习*Object类
java·开发语言·学习
invincible_Tang1 小时前
R格式 (15届B) 高精度
开发语言·算法·r语言
一只小松许️1 小时前
Rust闭包详解
开发语言·rust
快来卷java2 小时前
MySQL篇(一):慢查询定位及索引、B树相关知识详解
java·数据结构·b树·mysql·adb
独好紫罗兰2 小时前
洛谷题单2-P5715 【深基3.例8】三位数排序-python-流程图重构
开发语言·python·算法
凸头2 小时前
I/O多路复用 + Reactor和Proactor + 一致性哈希
java·哈希算法
阳光_你好2 小时前
详细说明Qt 中共享内存方法: QSharedMemory 对象
开发语言·数据库·qt
鹿屿二向箔2 小时前
阀门流量控制系统MATLAB仿真PID
开发语言·matlab
jiet_h2 小时前
深入解析Kapt —— Kotlin Annotation Processing Tool 技术博客
android·开发语言·kotlin