当前位置: 首页 > news >正文

指针运算典型例题解析

1.题目1

该代码运行的结果是什么?

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

解析:

运行结果:

2.题目2

在X86(32位)环境下,假设结构体的大小是20个字节,程序输出的结构是啥?

struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

解析:

考察的是“指针+-整数”的问题

+0x1就是结构体指针+1,要跳过一个结构体,结构体的大小是20个字节,所以就是+20字节 —— 如果是10进制则是:0x100020,但是现在是16进制,所以是0x100014

p 强制转换为 unsigned long,不是指针类型了,整型值+1,就是+1,所以是0x100001

unsigned int* 强制转换为,无符号整型的指针,+1是跳过一个整型的4个字节,所以是0x100004

运行结果:

3.题目3

#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}

解析:

调试一下,观察一下a中的内容:

不是:

01
23
45

的原因是因为:

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

不是:

int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };

所以,按照逗号表达式计算括号中保留了:1,3,5. 又因为是3行两列的,所以用 0 补位。

a[0] 是第一行的数组名,数组名表示首元素的地址,其实就是&a[0][0]

p[0] —— *(p + 0)——*p ——  1

运行结果:

4.题目4

假设环境是x86环境,程序输出的结果是啥?

#include <stdio.h>
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;
}

解析:

考察的是指针 - 指针,其结果的绝对值是指针和指针之间的元素个数。

a 是二维数组

p 是数组指针,p 指向的数组是 4 个整型元素的

分析如下:

%d 是打印有符号的整数

%p 是打印地址的

  1. 数组和指针的类型差异

    • a 是一个 int[5][5] 类型的二维数组。
    • p 是一个指向 int[4] 的指针,即每次移动会跳过 4 个 int
  2. 指针运算规则

    • 指针相减的结果是两个地址之间的元素个数,而非字节数。
    • &p[4][2] 相当于 p + 4*4 + 2 = p + 18(跳过 18 个 int)。
    • &a[4][2] 相当于 a + 4*5 + 2 = a + 22(跳过 22 个 int)。
  3. 地址计算

    • 假设 a 的起始地址为 0x0,则:
      • &p[4][2] 的地址为 0x0 + 18*4 = 0x48(每个 int 占 4 字节)。
      • &a[4][2] 的地址为 0x0 + 22*4 = 0x58
    • 地址差值为 0x48 - 0x58 = -0x10(即 - 16 字节),但指针相减结果为 -16 / 4 = -4

运行结果:

5.题目5

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

解析:

12345
678910

*(aa+1)—— aa[1]

aa[1] 是第二行的数组名

数组名表示首元素地址

aa[1] 也是 &aa[1][0]

&aa[1] 第二行的地址

sizeof(aa[1])计算的是第二行的大小

运行结果:

6.题目6

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

解析:

a 是指针数组

a 是 char* 型的

pa 是 char** 型的

*pa 就是解引用是 at

运行结果:

7.题目7

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

解析:

初始状态:

  • c 是一个字符指针数组,包含 4 个字符串常量的地址。

  • cp 是一个二级指针数组,初始化为 {c+3, c+2, c+1, c}

  • cpp 是一个三级指针,初始指向 cp 的起始位置。

第一次 printf**++cpp

  1. ++cpp 使 cpp 指向 cp[1](即 c+2)。

  2. *cpp 解引用得到 c+2

  3. **cpp 进一步解引用得到 c[2],即字符串 "POINT"

输出POINT

第二次 printf*--*++cpp+3

  1. ++cpp 使 cpp 指向 cp[2](即 c+1)。

  2. *cpp 得到 c+1

  3. --*cpp 将 c+1 减 1,变为 c(即 cp[3] 的原始值)。

  4. *--*cpp 解引用得到 c[0](字符串 "ENTER")。

  5. +3 跳过前 3 个字符,指向 "ER"

输出ER

第三次 printf*cpp[-2]+3

  1. cpp[-2] 等价于 *(cpp-2),指向 cp[0](即 c+3)。

  2. *cpp[-2] 解引用得到 c[3](字符串 "FIRST")。

  3. +3 跳过前 3 个字符,指向 "ST"

输出ST

第四次 printfcpp[-1][-1]+1

  1. cpp[-1] 指向 cp[1](即 c+2)。

  2. cpp[-1][-1] 等价于 *((c+2)-1),即 c[1](字符串 "NEW")。

  3. +1 跳过首字符,指向 "EW"

输出EW

关键注意点:

  • 指针运算直接修改了 cpp 和 cp 中的值(如 --*cpp)。

  • 下标访问(如 cpp[-2])基于当前 cpp 的位置计算。

  • 字符串偏移(如 +3)从字符串起始位置向后跳过指定字符数。

运行结果:

相关文章:

  • AI生成视频推荐
  • List接口
  • PySide6 GUI 学习笔记——常用类及控件使用方法(常用类边距QMarginsF)
  • RT-Thread 深入系列 Part 4:组件包管理与软件框架
  • Java动态代理超详细解析:三步+内存图(堆栈分析)
  • Linux进程间信号
  • ts装饰器
  • 从杰夫・托尔纳看 BPLG 公司的技术创新与发展
  • LeetCode 39 LeetCode 40 组合总和问题详解:回溯算法与剪枝优化(Java实现)
  • Python爬虫实战:获取woodo网各类免费图片,积累设计素材
  • [题解]2023CCPC黑龙江省赛 - Folder
  • 服务预热原理
  • 批量统计PDF页数,统计图像属性
  • 求数组中的两数之和--暴力/哈希表
  • Java 23种设计模式 - 行为型模式11种
  • JAVA——抽象类和接口的区别
  • A2A大模型协议及Java示例
  • jdk多版本切换,通过 maven 指定编译jdk版本不生效,解决思路
  • 使用lldb查看Rust不同类型的结构
  • cv_connection (像halcon一样对区域进行打散)
  • 中美经贸高层会谈在瑞士日内瓦开始举行
  • 经彩申城!上海网络大V沙龙活动走进闵行
  • 外卖员投资失败负疚离家流浪,经民警劝回后泣不成声给父母下跪
  • 大风暴雨致湖南岳阳县6户房屋倒塌、100多户受损
  • 马克思主义理论研究教学名师系列访谈|曾瑞明:想通了才可能认准,认准了才能做好
  • 中国以“大幅开放市场”回应贸易保护主义