帮忙看个程序到底是什么意思?

xxm0384182640 2012-02-09 11:41:46
#include <stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1);
int *ptr2=(int *)((int )a+1);
printf("%x,%x",ptr1[-1],*ptr2);
return 0;
}

运行结果为5,2000000
...全文
143 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
DyanWang 2012-02-10
  • 打赏
  • 举报
回复
#include <stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1);
int *ptr2=(int *)((int )a+1);
printf("%x,%x",ptr1[-1],*ptr2);
return 0;
}

&a是整个数组的地址,+1就到a[4]之后的哪一个空间了,因此ptr1[-1]就相当于是a[4],因此是5
a本来是一个常量指针,里面的内容是数组的首地址,(int)a相当于强行的把地址转换成int类型的数据,然后再+1,再将这个整数转换成指针类型赋值给ptr2,不是你想要的内容

如果将其改为int *ptr2=(int *)(a+1);那么*ptr2的值就为2了
junsborns 2012-02-10
  • 打赏
  • 举报
回复
建议楼主看看《C语言深度剖析》这本书,里面有你所要的答案。
赵4老师 2012-02-10
  • 打赏
  • 举报
回复
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
dos5gw 2012-02-10
  • 打赏
  • 举报
回复
再看ptr2,
int *ptr2=(int *)((int )a+1);

a被转换成整数, 然后+1, 这里的+1就相当于整数+1, 假设a代表的地址是0x11, (int )a+1就变成了0x12,
原本a指向的地址是"1", 它占4个字节, ptr2指向整数"1"的第二个字节,,,,ptr2的类型最后被强转为int*

然后打印*ptr2, 这时候打印什么呢, a[]的内存为1,2,3,4,5
这时候, ptr2指向的数, 是一个新组合的整数, 这个整数占4字节, 开头3字节是"1"的2~4字节, 结尾1字节是"2"的第1字节,
组合了自己算吧,



ps, 打印*ptr2的结果, 与机器的大小端还有关系
dos5gw 2012-02-10
  • 打赏
  • 举报
回复
这段代码告诉你, "指针+整数"这样的运算, 要注意指针的类型, 指针的类型不同, 就算加减同样的整数, 结果也不同,

(int*)p +1,
(double*)p+1,
(char*)p +1,
虽然都是指针p的运算, 但是, 指针移动的字节数不同的
dos5gw 2012-02-10
  • 打赏
  • 举报
回复
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1); //&a
int *ptr2=(int *)((int )a+1);
printf("%x,%x",ptr1[-1],*ptr2);
return 0;

这个意思,对于&a, 就是相当于"数组指针", 这个指针指向的类型是int[5],
&a+1, 就相当于, 指针+整数, 指针移动的字节=整数*sizeof(指向类型), 这里&a指向的类型是int[5], +1后指针向后移动了int[5]的长度, 就是20字节, 实际指向了元素"5"的后面, 然后把(&a+1)强转为int*, 那么这个int*类型的指针再加1减1, 就等于移动了一个int的字节, 莎哟~ptr1[-1] ,打印5
IVERS0N 2012-02-10
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yang122610 的回复:]

http://topic.csdn.net/u/20071127/17/d521c586-bc0a-4c31-bcfe-5d90f0ed7c5e.html?96950
[/Quote]
AnYidan 2012-02-10
  • 打赏
  • 举报
回复
自己单步运行下
动感超哥 2012-02-09
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20071127/17/d521c586-bc0a-4c31-bcfe-5d90f0ed7c5e.html?96950
Binzo 2012-02-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 programmingring 的回复:]

...ptr是a的地址+1然后取值
[/Quote]
这不对。
ProgrammingRing 2012-02-09
  • 打赏
  • 举报
回复
ptr1指向了a[4]的后面,然后减1即5,ptr是a的地址+1然后取值
内容概要:本文档提供了适用于算法竞赛的Java语言模板代码,重点涵盖动态规划与图论两大核心领域。动态规划部分包括01背包、完全背包、多重背包的二进制拆分优化、最长上升子序列(LIS)的O(n log n)解法以及最长公共子序列(LCS)的标准DP实现。图论部分涵盖了Dijkstra(堆优化)、SPFA(可检测负环)、Floyd-Warshall(多源最短路径)、Kruskal和Prim(最小生成树)等经典算法。此外还包含网络流领域的Dinic算法完整模板及其使用示例,适用于解决最大流问题。所有代码均以简洁高效的竞赛风格编写,具备直接应用价值。; 适合人群:具备Java编程基础,正在准备程序设计竞赛(如ACM/ICPC、蓝桥杯、力扣周赛等)的学生或开发者,尤其是对算法实现细节有较高要求的中高级选手。; 使用场景及目标:①快速查阅和复用经典算法模板,提升竞赛中的编码效率;②深入理解动态规划与图论算法的核心实现机制,强化算法调试与优化能力;③通过Dinic等高级算法掌握网络流问题的建模与求解方法; 阅读建议:建议结合实际题目进行练习,理解每段代码的边界条件与数据结构设计,注重对算法复杂度和适用范围的掌握,并在实践中不断优化个人模板库。

70,037

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧