(代码已贴出)在32位的X86系统下,输出的值是5,2000000,烦请明白的帮忙说下为什么,不怎么理解

andylfg 2013-08-09 12:01:34
//这一小段程序是在《C语言深度解剖》中的一小段程序,没有给出说明
#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;
}
...全文
471 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
andylfg 2013-08-10
  • 打赏
  • 举报
回复
昨天忘了结贴,已经结贴
canshui 2013-08-09
  • 打赏
  • 举报
回复
引用 2 楼 liyanfasd 的回复:
&a+1 指向的是下一个大小为sizeof(a)的数组。 ((int)a + 1) 将地址转化为整形,再进行+1,类似于char型指针+1.指向的数值与平台的大小端模式是有关系的。
nice ...
大漠孤鸿 2013-08-09
  • 打赏
  • 举报
回复

&a+1 指向的是下一个大小为sizeof(a)的数组。
((int)a + 1) 将地址转化为整形,再进行+1,类似于char型指针+1.指向的数值与平台的大小端模式是有关系的。
大漠孤鸿 2013-08-09
  • 打赏
  • 举报
回复


&a+1 指向的是下一个大小为sizeof(a)的数组。
((int)a + 1) 将地址转化为整形,再进行+1,类似于char型指针+1.指向的数值与平台的大小端模式是有关系的。
max_min_ 2013-08-09
  • 打赏
  • 举报
回复

printf("% x, %x\n", ptr1[-1], *ptr2);
printf("% p, %x\n", *ptr2, *ptr2); 


本质上来讲a[-1]就跟*(a-1)一样,所以是负数也无可后非了 

http://blog.csdn.net/code_crash/article/details/4855000 
可以看看这个博客里的 运算符的本质介绍!
max_min_ 2013-08-09
  • 打赏
  • 举报
回复
引用 10 楼 andylfg 的回复:
[quote=引用 1 楼 max_min_ 的回复:]

printf("% x, %x\n", ptr1[-1], *ptr2);
printf("% p, %x\n", *ptr2, *ptr2); 


本质上来讲a[-1]就跟*(a-1)一样,所以是负数也无可后非了 

http://blog.csdn.net/code_crash/article/details/4855000 
可以看看这个博客里的 运算符的本质介绍!
感谢二楼给出的地址,十分感谢[/quote] 问题解决了, 结贴是个好习惯!
andylfg 2013-08-09
  • 打赏
  • 举报
回复
引用 1 楼 max_min_ 的回复:

printf("% x, %x\n", ptr1[-1], *ptr2);
printf("% p, %x\n", *ptr2, *ptr2); 


本质上来讲a[-1]就跟*(a-1)一样,所以是负数也无可后非了 

http://blog.csdn.net/code_crash/article/details/4855000 
可以看看这个博客里的 运算符的本质介绍!
感谢二楼给出的地址,十分感谢
赵4老师 2013-08-09
  • 打赏
  • 举报
回复
1:    //这一小段程序是在《C语言深度解剖》中的一小段程序,没有给出说明
2:    int a[5] = {1, 2, 3, 4, 5};
3:    int* ptr1 = (int*) (&a + 1);
4:    int* ptr2 = (int*) ((int)a + 1);
5:
6:    int t;
7:    int main()
8:    {
00401000 55                   push        ebp
00401001 8B EC                mov         ebp,esp
00401003 83 EC 40             sub         esp,40h
00401006 53                   push        ebx
00401007 56                   push        esi
00401008 57                   push        edi
9:        t=ptr1[-1];
00401009 A1 24 30 40 00       mov         eax,[ptr1 (00403024)]
0040100E 8B 48 FC             mov         ecx,dword ptr [eax-4]
00401011 89 0D 40 30 40 00    mov         dword ptr [t (00403040)],ecx
10:       t=*ptr2;
00401017 8B 15 28 30 40 00    mov         edx,dword ptr [ptr2 (00403028)]
0040101D 8B 02                mov         eax,dword ptr [edx]
0040101F A3 40 30 40 00       mov         [t (00403040)],eax
11:       return 0;
00401024 33 C0                xor         eax,eax
12:   }
00401026 5F                   pop         edi
00401027 5E                   pop         esi
00401028 5B                   pop         ebx
00401029 8B E5                mov         esp,ebp
0040102B 5D                   pop         ebp
0040102C C3                   ret

00403010  01 00 00 00 02 00 00 00 03 00 00  ...........
0040301B  00 04 00 00 00 05 00 00 00

+	a	0x00403010
+	&a	0x00403010
	a[5]	4206628
+	ptr1	0x00403024
+	ptr2	0x00403011
	t	0
赵4老师 2013-08-09
  • 打赏
  • 举报
回复
1:    //这一小段程序是在《C语言深度解剖》中的一小段程序,没有给出说明
2:    int main()
3:    {
00401000 55                   push        ebp
00401001 8B EC                mov         ebp,esp
00401003 83 EC 60             sub         esp,60h
00401006 53                   push        ebx
00401007 56                   push        esi
00401008 57                   push        edi
4:        int a[5] = {1, 2, 3, 4, 5};
00401009 C7 45 EC 01 00 00 00 mov         dword ptr [ebp-14h],1
00401010 C7 45 F0 02 00 00 00 mov         dword ptr [ebp-10h],2
00401017 C7 45 F4 03 00 00 00 mov         dword ptr [ebp-0Ch],3
0040101E C7 45 F8 04 00 00 00 mov         dword ptr [ebp-8],4
00401025 C7 45 FC 05 00 00 00 mov         dword ptr [ebp-4],5
5:        int* ptr1 = (int*) (&a + 1);
0040102C 8D 45 00             lea         eax,[ebp]
0040102F 89 45 E8             mov         dword ptr [ebp-18h],eax
6:        int* ptr2 = (int*) ((int)a + 1);
00401032 8D 4D ED             lea         ecx,[ebp-13h]
00401035 89 4D E4             mov         dword ptr [ebp-1Ch],ecx
7:
8:        int t;
9:        t=ptr1[-1];
00401038 8B 55 E8             mov         edx,dword ptr [ebp-18h]
0040103B 8B 42 FC             mov         eax,dword ptr [edx-4]
0040103E 89 45 E0             mov         dword ptr [ebp-20h],eax
10:       t=*ptr2;
00401041 8B 4D E4             mov         ecx,dword ptr [ebp-1Ch]
00401044 8B 11                mov         edx,dword ptr [ecx]
00401046 89 55 E0             mov         dword ptr [ebp-20h],edx
11:       return 0;
00401049 33 C0                xor         eax,eax
12:   }
0040104B 5F                   pop         edi
0040104C 5E                   pop         esi
0040104D 5B                   pop         ebx
0040104E 8B E5                mov         esp,ebp
00401050 5D                   pop         ebp
00401051 C3                   ret
赵4老师 2013-08-09
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单! 指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认: 有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物; 而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。 这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图,画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗?本人深表怀疑! 这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条,烤面包,……能从本质上理解面粉、理解面食吗?本人深表怀疑!! 提醒: “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 (Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 想要从本质上理解C指针,必须学习C和汇编的对应关系。” 不是一回事! 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码! 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息…… 十字链表交换任意两个节点C源代码(C指针应用终极挑战)http://download.csdn.net/detail/zhao4zhong1/5532495
hordemark 2013-08-09
  • 打赏
  • 举报
回复
引用 3 楼 liyanfasd 的回复:
&a+1 指向的是下一个大小为sizeof(a)的数组。 ((int)a + 1) 将地址转化为整形,再进行+1,类似于char型指针+1.指向的数值与平台的大小端模式是有关系的。
good job.
mujiok2003 2013-08-09
  • 打赏
  • 举报
回复
引用 2 楼 liyanfasd 的回复:
&a+1 指向的是下一个大小为sizeof(a)的数组。 ((int)a + 1) 将地址转化为整形,再进行+1,类似于char型指针+1.指向的数值与平台的大小端模式是有关系的。

69,382

社区成员

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

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