蛮有意思的代码!

zecard_fu 2010-08-04 05:58:55
以下代码请在以下环境编译
cpu: intel
os: linux32位
编译器: gcc 4.1 以上版本
有兴趣的编译看看! 然后说下结果~ 然后讨论下哈~ 共同进步~~

#include <stdio.h>

int main()
{
int *b, k, i, j, h;
int a, *g, *l;
char *f;

struct hup{
int n;
int m;
}hup;

b = &i;

for (i=0; i<7; i++) {

if (i == 6)
*(&hup.m+((&l-&g)&0x1+2)) = 1;
else
printf("oh! my god!");
}

return 0;
}



...全文
1172 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-08-05
  • 打赏
  • 举报
回复
用GDB调试时,看每句C对应的汇编。
Wind_Runner 2010-08-05
  • 打赏
  • 举报
回复
好牛b的代码
water0_ 2010-08-05
  • 打赏
  • 举报
回复
迷糊中...........
cranium 2010-08-04
  • 打赏
  • 举报
回复

b = &i;


这小小的一句代码,不知道让GCC犯什么迷,硬是将i和b的位置调在一起,使得原本有点规律的内存布局就这么被打乱了。

C标准里难道没有规定局部变量入栈顺序?
hjbxyz 2010-08-04
  • 打赏
  • 举报
回复
没意思!
bobo364 2010-08-04
  • 打赏
  • 举报
回复
有意思,看来这个代码真要看汇编了,等赵中来提取并分析下汇编代码
#include <stdio.h>

int main()
{
int *b,k,i,j,h;
int a,*g,*l;
char *f;

struct hup
{
int n;
int m;
}hup;

b=&i;

for (i=0; i<7; i++)
{
if (i == 6)
{
*(&hup.m+((&l-&g)&0x1+2)) = 1;
}
else
{
printf("oh! my god!\n");
}
}
system("pause");
return 0;
}
cranium 2010-08-04
  • 打赏
  • 举报
回复
而且很混啊,在MinGW GCC版本4.4.1 + win7下 codeblocks IDE的环境下debug调试,这些个int,还有int* 们都很安分的占这自己的4个字节。

但是在vs2010下由于debug,每一个变量还要在堆栈上多分配8个字节的长度,导致调试状态下
int a;
int b;
&a-&b 的值为3..就是中间差了3个int的字节。
(vs2010 release下正常占有4字节,而不是debug下的4+8)
cranium 2010-08-04
  • 打赏
  • 举报
回复
MinGW GCC版本4.4.1 + win7下 codeblocks IDE

调试了半天,确定了内存布局并非我在7楼按常理想的那样,实际的内存分布是:

//*仅为方便代表对象是个指针,这儿无其他含义
//此布局为上面环境下本程序的真实堆栈描述
n
m
*l
*g
i
*b
k
j
h
a
*f


*(&hup.m+((&l-&g)&0x1+2)) 表达是的求值过程(根据以上布局):
&l-&g ---> -1
(&l-&g)&0x1 ---> 1
((&l-&g)&0x1+2) ---> 3
(&hup.m + 3) ---> 根据上面的布局,可以很明显的看出这是 i 的地址。
*(&hup.m +3) = 1; ---> i赋值为1

实际情况就像上面那样了。

——————————————————————————————————————————
其实我也很纳闷啊,布局怎么成那样了???
cranium 2010-08-04
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 foolbirdflyfirst 的回复:]
linux gcc 4.4.3
好象没什么异常嘛。。
[/Quote]

我在7楼所说的后来发现全是错误的,对不住大家浪费大家眼神了。
foolbirdflyfirst 2010-08-04
  • 打赏
  • 举报
回复
输出5次oh,my god.然后回车退出。
foolbirdflyfirst 2010-08-04
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cranium 的回复:]

C/C++ code

//我感觉的堆栈分布是
//低地址在上,高地址在下
n
m
f
l
g
a
h
j
i
k
b


一下代码我的解释是:
C/C++ code
*(&hup.m+((&l-&g)&0x1+2)) = 1;


&l-&g为sizeof(int*),一般该是个偶数吧,比如4
所以(&l-&g)&……
[/Quote]
linux gcc 4.4.3
好象没什么异常嘛。。
canshui 2010-08-04
  • 打赏
  • 举报
回复
我太白了,实在没感觉到这有什么意思!
NoOO7 2010-08-04
  • 打赏
  • 举报
回复
有点意思的代码呵呵
azhanglinyang 2010-08-04
  • 打赏
  • 举报
回复
是挺有意思的!
huandfly 2010-08-04
  • 打赏
  • 举报
回复
衣柜和衣服的区别!想在衣柜取衣服,必须确定衣柜里有衣服。
cranium 2010-08-04
  • 打赏
  • 举报
回复

//我感觉的堆栈分布是
//低地址在上,高地址在下
n
m
f
l
g
a
h
j
i
k
b


一下代码我的解释是:
*(&hup.m+((&l-&g)&0x1+2)) = 1;


&l-&g为sizeof(int*),一般该是个偶数吧,比如4
所以(&l-&g)&x1就等于加了一个1,结果是((&l-&g)&0x1+2) == 7
又由于&hup.m是一个int*,所以(&hup.m+((&l-&g)&0x1+2))这个结果就是一个堆栈上的定位,向高地址移动了7个int的长度,恰好执行了i

对这个指针去值,然后赋值为1。

结果就是i好不容易到6了,又回到了1,然后又开始循环。

qgqch2008 2010-08-04
  • 打赏
  • 举报
回复
xpup。
duke56 2010-08-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zxk860611 的回复:]
&hup.m 是取成员地址
hup.m 是访问成员

vs2005编译没见问题,LZ不妨说下在你那个特定环境下的结果
[/Quote]

应该是输出5次的字符吧...

不清楚Linux下的编译器会把它编译成怎么个样子的
duke56 2010-08-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mashrb 的回复:]
看不懂,我刚看到 结构 这一节,所以有个问题问楼下的,通过 &hup.m 访问成员与通过 hup.m 访问成员有什么不同吗??有劳!!
[/Quote]

&是取地址符,也就是通过结构体的地址去访问

可以理解为指针的访问方式(是方式!)
zxk860611 2010-08-04
  • 打赏
  • 举报
回复
&hup.m 是取成员地址
hup.m 是访问成员

vs2005编译没见问题,LZ不妨说下在你那个特定环境下的结果
加载更多回复(2)

69,371

社区成员

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

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