Chinaunix首页 | 论坛 | 博客
  • 博客访问: 147335
  • 博文数量: 17
  • 博客积分: 2146
  • 博客等级: 大尉
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-07 23:26
文章分类

全部博文(17)

文章存档

2011年(1)

2009年(5)

2008年(11)

分类:

2008-08-08 05:31:05

前一段时间在论坛看到讨论关于“栈上改变值参的方法”的问题和方法,觉得十分有趣,自己也小试了一下。
原问题类似如下:
 
#include
int test(int a)
{
//请写段代码,让main中打印的a的值前后不等。如第一个printf打印a=100,第二个printf打印a=200
}
int main()
{
 int a = 100;
 printf("a=%d\n",a);
 test(a);
 printf("a=%d\n",a);
 system("pause");
 return 0;
}
 
关于linux下gcc的写法这里就不说了,好多大牛都给出了详细解释,这里俺又做了vc80下的测试。可以说是几经痛苦的调试呵呵,才发现这个幻数53,主要是对编译器,反汇编不熟悉。代码如下
#include
#define MAGIC_NUMBER 53
int test(int a)
{
//请写段代码,让main中打印的a的值前后不等。如第一个printf打印a=100,第二个printf打印a=200
*(&a + MAGIC_NUMBER ) = 200;
}
int main()
{
 int a = 100;
 printf("a=%d\n",a);
 test(a);
 printf("a=%d\n",a);
 system("pause");
 return 0;
}
推广一下,对于多个参数,可以这样写
 
#include
#define MAGIC_NUMBER 53
int test(int a,int v)
{
 int b = 500;
 *(&a + MAGIC_NUMBER +  sizeof(int)) = 200;
 *(&v + MAGIC_NUMBER ) = 200;
}
int main()
{
 int a = 100;
 int v = 0;
 printf("a=%d\n",a);
 printf("a=%d\n",a);
 test(a,0);
 printf("a=%d\n",a);
 printf("v=%d\n",v);
 system("pause");
 return 0;
}
这样打印出的a,v,满足了要求。您没看错吧?这句test(a,0);是不是有问题啊?我没有传v进去啊!本来纯属我的笔误,可是运行出来v的的确确是200!晕倒ing...
看来结果正确纯属侥幸,并没有找到原理,再试一下
#include
#define MAGIC_NUMBER 53
int test(int a,int v)
{
 int b = 500;
 *(&a + MAGIC_NUMBER +  sizeof(int)) = 200;
 *(&v + MAGIC_NUMBER ) = 200;
}
int main()
{
 
 int a = 100;   
 int c = 0;               
 int v = 0;
 test(a,v);
 printf("a=%d\n",a);
 printf("v=%d\n",v);
 system("pause");
 return 0;
}
结果v是符合要求了,而a则不正确,这下可以看出来了,由于c的引入,改变了a,c的内存位置。而相邻的两个变量地址之差值为3.所以还是可以算的。再来!
#include
#define MAGIC_NUMBER 53
#define STEP 3
int test(int a,int v)
{
 //int b = 500;
 *(&a + MAGIC_NUMBER + 4*STEP + 1) = 200;  //从a到v共4个int(含v)
 *(&v + MAGIC_NUMBER ) = 200;
}
int main()

 int a = 100;
 int c = 10; 
 int d;
 int f;
 int v = 0;
 test(a,v);
 printf("a=%d\n",a);
 printf("v=%d\n",v);
 system("pause");
 return 0;
}
这个规律不明显,再改造一下,改用v的地址
 
#include
#define MAGIC_NUMBER 53
#define STEP 3
int test(int a,int v)
{
 //int b = 500;
 *(&v + MAGIC_NUMBER + 4*STEP) = 200;//从a到v共4个int(含v)
 *(&v + MAGIC_NUMBER ) = 200;
}
int main()

 int a = 100;
 int c = 10; 
 int d;
 int f;
 int v = 0;
 test(a,v);
 printf("a=%d\n",a);
 printf("v=%d\n",v);
 system("pause");
 return 0;
}
这次一定程度上满足了要求,但是必须记得变量之间的跨度,而且v的位置很关键,再试试其他数据类型
#include
#define MAGIC_NUMBER 53
//#define STEP 3
int test(int a,int step)
{
 //int b = 500;
 *(&step + MAGIC_NUMBER + step) = 200;//a
}
int main()

 int a = 100;
 int b;
 double dd;
 double ddd; 
 int step = 2*(sizeof(int) -1) + 2* sizeof(double) /2;
 test(a,step);
 printf("a=%d\n",a);
 system("pause");
 return 0;
}
也可以计算出。
阅读(1124) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~