问答题 是否可以通过绝对内存地址进行参数赋值与函数调用
【正确答案】
【答案解析】同一个数可以通过不同的方式表达出来,对于函数的访问,变量的赋值除了直接对变量赋值以外,还可以通过绝对内存地址进行参数赋值与函数调用。
1)通过地址修改变量的值。
int x;
int *p;
printf("%x/n",&x);
p=(int*)0x0012ff60;
*p=3;
printf("%d/n",x);
程序的输出结果:
12ff60
3
程序首先输出变量X所在地址为十六进制的0x12ff60(本来应该为8位的十六进制数,高位为0则省略掉),然后定义一个指针变量,让它指向该地址,通过指针变量的值来修改变量x的值。
示例代码如下:
int *ptr=(int*)0xa4000000;
*ptr=0xaabb;
printf("%d/n",*ptr);
以上程序会崩溃,因为这样做会给一个指针分配一个随意的地址,很危险,所以这种做法是不允许的。
2)通过地址调用函数的执行。
#include<iostream>
using namespace std;
typedef void(*FuncPtr)();
void p()
{
printf("MOP/n");
}
int main()
{
void(*ptr)();
p();
printf("%x/n",p);
ptr=(void(*)())0x4110f0;
ptr();∥函数指针执行
((void(*)())0x4110f0)();
((FuncPtr)0x4110f0)();
return 0;
}
程序执行结果如下:
MOP
4110f0
MOP
MOP
MOP
首先定义一个ptr的函数指针,第一次通过函数名调用函数,输出Mop,打印函数的入口地址,函数的入口地址为4110f0。然后给函数指针ptr赋地址值为P的入口地址,调用ptr,输出Mop。接着的过程不通过函数指针直接执行,仍然使用P的入口地址调用,输出为MOP。最后是通过typedef调用的直接执行。
函数名称、代码都是放在代码段的,因为放在代码段,每次会跳到相同的地方,但参数会压栈,所以函数只根据函数名来获取入口地址,与参数和返回值无关。无论参数和返回值如何不同,函数入口地址都是一个地方。
对以下程序进行分析:
#include<stdio.h>
int p(int a,int b)
{
return 3;
}
int main()
{
printf("%x/n",p);
int a=p(2,3);
prinftf("%d/n",p);
int b=p(4,5);
printf("%x/n",p);
return 0;
}
程序输出结果如下:
411159
4264281
411159
十六进制的411159转换成十进制的值为4264281。程序中打印的P的入口地址,无论P是否调用函数,入口地址都没有改变。
分析如下代码:
#include<stdio.h>
int p(int a,int b)
{
return((a>b)?a:b);
}
int main()
{
int(*ptr)(int,int);
ptr=(int(*)(int,int))0x411159;
int c=ptr(5,6);
printf("%d/n",c);
return 0;
}
程序输出结果:
6
通过函数指针调用有返回值和参数的函数,不使用函数名,而是用函数入口地址调用。
函数存放在内存的代码区域内,也有地址,一个函数在编译时被分配一个入口地址,将这个入口地址称为函数的指针,函数的地址就是函数的名字。函数指针不能指向不同类型或是带不同形参的函数。