C语言实现程序跳转到绝对地址0x100000处执行
嵌入式笔试题:想让程序跳转到绝对地址0x100000处执行,该如何做?
请详细解释一下所给的答案:
网上看到有如下答案:
*((void(*)(void))0x100000)();
经过在VC++6.0和LINUX gcc4.4.3下测试,均不能通过编译。
VC++6.0报错:error C2100: illegal indirection
GCC报错:error: void value not ignored as it ought to be
应该是怎么写呢?
经过测试,有两种方法:
答案1. (*(void(*)(void))0x100000)();
答案2. ((void(*)(void))0x100000)();
仔细观察,第一种写法只是第一个*的位置不同,第二种写法少了一个*,但是都能正确编译通过,且正确执行。
为什么会有这两种答案呢?查阅资料后发现,与历史原因有关……
先来看看如下例子:
例一:
- #include <stdio.h>
- void func(void)
- {
- printf("hello.\n");
- }
- void main(void)
- {
- printf("func=%d\n", func);
- printf("&func=%d\n", &func);
- }
运行程序后发现
两次打印结果相同!!!
按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&func是非法的,但很久以前有些编译器已经允许这样做,c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&func的合法性。
因此,对于func和&func可以这样理解,func是函数的首地址,它的类型是void (),&func表示一个指向函数void func(void)这个对象的地址,它的类型是void (*)(),因此func和&func所代表的地址值是一样的,但类型不一样。func是一个函数,&func表达式的值是一个指针!
既然取不取址都可以,那么*不*也都可以……
所以,在调用一个函数的时候,也有两种方法,正如前面的两种答案。
例二:
- #include <stdio.h>
- void func(void)
- {
- printf("hello.\n");
- }
- void main()
- {
- void (*func_p)(void) = func; //定义一个函数指针,这个指针无返回值,无参数,指向fun函数
- (*func_p)();
- (func_p)();
- }
上面的两种调用方法也都是正确的,编译通过,正确执行。
其实,
- func_p();
也是正确的调用方式……
更有甚者
- (*func)();
还是正确的……只是平时不这么用罢了(注意此处是func,不是func_p)
暂且不考虑那么多调用方式(知道就好了),现在回过头来看看
- (*(void(*)(void))0x100000)();
和
- ((void(*)(void))0x100000)();
到底是什么东东……
1.首先来认识一个新的数据类型,如:void (*)(void),和 int* 类似的一个数据类型,只不过int*是一个指向int型的指针,而void (*)(void)是一个指向函数的指针,且这个函数无返回值,无参数。
2.然后给他外层加个括号,如:(void (*)(void)),这样是不是很像(int*),我们在做强制类型转换的时候需要在类型外加个括号的是吧。
3.接着把0x100000强制转化为一个函数指针,即:(void(*)(void))0x100000
4.最后就是调用这个函数,外层再加个括号,后面在加一对括号(参考例二的形式),
如:((void(*)(void))0x100000)();就可以到绝对地址0x100000处去执行了……
或者(*(void(*)(void))0x100000)();只是加不加 * 的问题。上面例二中可以看出,在用函数指针调用一个函数时,加不加 * 都是可以的。
所以答案就出来了……
另外,你可能疑惑,按照例二中func_p(); 的形式,那么 (void(*)(void))0x100000();也应该对呀?
但是,实际测试,编译报错:error C2064: term does not evaluate to a function
为啥呢?我也不知道了……反正不管有没有 * ,记得加个括号就好了……
那为什么最开始的*((void(*)(void)0x100000))();不对呢?
因为没见过*func(); 这么用的……
如果要是外面再加一层括号就对了,如:(*( (void(*)(void)0x100000) )) ();
其实,把蓝色括号去掉(蓝色括号和绿色括号重复了),就又变成答案一了……
所以无论如何,最外层不能是* ,必须是括号!
因为没见过 *func(); 这么用的……
C语言实现程序跳转到绝对地址0x100000处执行的更多相关文章
- 让程序跳转到绝对地址0x100000去执行
网上比较火的一个题,让程序跳转到绝对地址去执行 :可以的实现方式为: ( (void(*)())0x4110e6)(); (*(void(*)())0x4110e6)(); (*((void(*)() ...
- 要是想让程序跳转到绝对地址是0x100000去执行
要对绝对地址0x100000赋值,我们可以用 (unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? *((void (* ...
- C语言面试程序阅读整理
一.数组和指针 1.数组和指针的存储 写出下面的输出结果: char str1[] = "abc"; char str2[] = "abc"; const ch ...
- 通过反汇编C语言小程序学习Liunx汇编语言
大家好! 我是来自山东师范大学的吴乐. 今天在<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...
- Linux下简单C语言小程序的反汇编分析
韩洋原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 写在开始,本文为因为参加MOO ...
- 4_PHP流程控制语句_3_程序跳转和终止语句
以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. PHP流程控制共有3种类型:条件控制结构.循环结构以及程序跳转和终止语句. 4.3 程序跳转和终止语句 4.3.1 ...
- R语言服务器程序 Rserve详解
R语言服务器程序 Rserve详解 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒.直到 ...
- Hybrid App是如何实现网页语言与程序语言的混合?谁占主体?
[编者按]本文作者@徐珂铭,一位看好Html5的移动互联网的从业人士.喜爱玩技术,会点JAVA.HTML及CSS,有自己的想法及姑且能表达想法的文字,因此有了自己的文章. 基于HTML5的Web Ap ...
- windows系统下c语言暂停程序
原文:windows系统下c语言暂停程序 windows系统下,很多C语言初学者的调试时,往往没看到结果程序就退出了,据我所知的方法主要有以下几种 方法一: #include int main() { ...
随机推荐
- 阻塞式I/O实现简单TCP通信
一.技术简介 (1)服务端打开两个端口9999和6666监听外来连接: (2)服务端的子进程通过端口9999监听外来消息,通过端口6666发送消息: (3)客户端的子进程处理外来消息,父进程发送消息 ...
- 【核心】project(idea文件)、module(iml文件)到SSM集成、热部署、Tomcat启动、MAVEN依赖冲突
http://wiki.jikexueyuan.com/project/intellij-idea-tutorial/project-composition-introduce.html 在 Inte ...
- Ubuntu中创建、删除、更改、移动文件的命令
1.创建一个目录 $ sudo mkdir <目录名> 2.删除一个非空目录下的一切 $ sudo rm -rf <目录名> 3.将文件file1,更改文件名为file ...
- PHP WeBaCoo后门学习笔记
PHP WeBaCoo后门学习笔记 - PHP WeBaCoo backdoor learning notes WeBaCoo (Web Backdoor Cookie) 是一款隐蔽的脚本类Web后门 ...
- MySQL安装 8.0.15版本
windows下MySQL 8.0.15的安装和设置 MySQL下载地址:https://dev.mysql.com/downloads/mysql/ 我的百度网盘下载(win64位):链接:http ...
- git修改文件夹名字
git mv -f oldfolder newfolder git add -u newfolder (-u选项会更新已经追踪的文件和文件夹) git commit -m "changed ...
- 使用AOP AspectJ 定义@Before,@After ,@Aroud后 执行两次
背景 转眼之间,发现博客已经将近半年没更新了,甚是惭愧.话不多说,正如标题所言,最近在使用AspectJ的时候,发现拦截器(AOP切面)执行了两次了.我们知道,AspectJ是AOP的一种解决方案,本 ...
- (6)Java数据结构-- 转:JAVA常用数据结构及原理分析
JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balab ...
- i春秋 小漏洞也有大梦想
i春秋上的课,提到了一些概念,学习并记录. 此文主要以了解概念为主,没有代码和实战. 水坑式攻击 百度定义: “水坑式攻击”,是指黑客通过分析被攻击者的网络活动规律,寻找被攻击者经常访问的网站的弱点, ...
- Aizu - 2249 Road Construction
题目:给出若干个建筑之间的一些路,每条路都有对应的长度和需要的花费,问在保证源点1到其他个点的距离最短的情况下,最少的花费是多少/ 思路:和一般的最短路问题相比,多了一个 数组id[i],用来记录到达 ...