理解(*(void(*)())0)();
程序员文章站
2022-05-01 10:38:08
...
先说一下强制转换,可以跳过。例子:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t a = 0xA5A1;
uint8_t b;
b = (uint8_t)a; // 16位强制转换为8位
printf("b=0x%X",b);
}
a是16位,b是8位,将a进行一次强制转换的结果给b。
我这里的输出结果是
b=0xA1
---------------------------------------正文----------------------------------------
我这里执行之后得到的结果是
funa is called
0x401530
第一行表示funa函数已经执行
第二行表示funa函数的地址为0x401530(在不同机器不同时间结果可能都不同)
以这里的结果为例,此时将上述代码的第11、12行改为
运行结果是相同的。
但是将11、12行合并为:
(*0x401530)();
编译器会报错。
也就是说,我们需要将 "0x401530"强制转换为函数地址
参照最开始的强制转换,这里的格式应该大体是这样的:
(*(_______)0x401530)();
接下来只需要考虑下划线里该填什么了
参照之前的
void (*p)(); // 定义一个函数指针
我们可以知道,下划线里应该写
void (*)()
那么结果就出来了,这里要想将11、12行合并为一句,只需要这么写:
我这里修改之后的最终程序为:
输出和之前是完全相同的。
--------------------------------------归题--------------------------------------
如果我们需要运行位于0地址处的函数(或者是从0地址处开始运行)
只需把上面的0x401530改成0即可
也就是
(*(void(*)())0)();
---------------------------------------拓展----------------------------------------
如果真的理解之后,可以配合typedef使用。
之前的例子可以这样写
参考资料: <C的陷阱与缺陷> 2.1章 Andrew Koenig著
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t a = 0xA5A1;
uint8_t b;
b = (uint8_t)a; // 16位强制转换为8位
printf("b=0x%X",b);
}
a是16位,b是8位,将a进行一次强制转换的结果给b。
我这里的输出结果是
b=0xA1
---------------------------------------正文----------------------------------------
include <stdio.h> void funa(void) { printf("funa is called\n"); } int main() { void (*p)(); // 定义一个函数指针 p=funa; // p中存放funa函数地址 (*p)(); // 运行funa printf("0x%X",&funa); // 打印funa函数的地址 return 0; }
我这里执行之后得到的结果是
funa is called
0x401530
第一行表示funa函数已经执行
第二行表示funa函数的地址为0x401530(在不同机器不同时间结果可能都不同)
以这里的结果为例,此时将上述代码的第11、12行改为
p=0x401530; (*p)();
运行结果是相同的。
但是将11、12行合并为:
(*0x401530)();
编译器会报错。
也就是说,我们需要将 "0x401530"强制转换为函数地址
参照最开始的强制转换,这里的格式应该大体是这样的:
(*(_______)0x401530)();
接下来只需要考虑下划线里该填什么了
参照之前的
void (*p)(); // 定义一个函数指针
我们可以知道,下划线里应该写
void (*)()
那么结果就出来了,这里要想将11、12行合并为一句,只需要这么写:
(* (void (*)())0x401530)();
我这里修改之后的最终程序为:
#include<stdio.h> void funa(void) { printf("funa is called\n"); } int main() { (*(void(*)())0x401530)(); // 运行位于0x401530地址处的funa函数 printf("0x%X",&funa); // 打印funa函数的地址 return 0; }
输出和之前是完全相同的。
--------------------------------------归题--------------------------------------
如果我们需要运行位于0地址处的函数(或者是从0地址处开始运行)
只需把上面的0x401530改成0即可
也就是
(*(void(*)())0)();
---------------------------------------拓展----------------------------------------
如果真的理解之后,可以配合typedef使用。
之前的例子可以这样写
#include<stdio.h> typedef void (*funcptr)(); // 为函数指针类型定义别名funcptr void funa(void) { printf("funa is called\n"); } int main() { (*(funcptr)0x401530)(); // 运行位于0x401530地址处的funa函数 printf("0x%X",&funa); // 打印funa函数的地址 return 0; }
参考资料: <C的陷阱与缺陷> 2.1章 Andrew Koenig著