嵌入式笔试题:想让程序跳转到绝对地址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)();

仔细观察,第一种写法只是第一个*的位置不同,第二种写法少了一个*,但是都能正确编译通过,且正确执行。

为什么会有这两种答案呢?查阅资料后发现,与历史原因有关……

先来看看如下例子:

例一:

  1. #include <stdio.h>
  2. void func(void)
  3. {
  4. printf("hello.\n");
  5. }
  6. void main(void)
  7. {
  8. printf("func=%d\n", func);
  9. printf("&func=%d\n", &func);
  10. }

运行程序后发现

两次打印结果相同!!!

按照&运算符本来的意义,它要求其操作数是一个对象,但函数名不是对象(函数是一个对象),本来&func是非法的,但很久以前有些编译器已经允许这样做,c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&func的合法性。
因此,对于func和&func可以这样理解,func是函数的首地址,它的类型是void (),&func表示一个指向函数void func(void)这个对象的地址,它的类型是void (*)(),因此func和&func所代表的地址值是一样的,但类型不一样。func是一个函数,&func表达式的值是一个指针!

既然取不取址都可以,那么*不*也都可以……

所以,在调用一个函数的时候,也有两种方法,正如前面的两种答案。

例二:

  1. #include <stdio.h>
  2. void func(void)
  3. {
  4. printf("hello.\n");
  5. }
  6. void main()
  7. {
  8. void (*func_p)(void) = func;        //定义一个函数指针,这个指针无返回值,无参数,指向fun函数
  9. (*func_p)();
  10. (func_p)();
  11. }

上面的两种调用方法也都是正确的,编译通过,正确执行。

其实,

  1. func_p();

也是正确的调用方式……

更有甚者

  1. (*func)();

还是正确的……只是平时不这么用罢了(注意此处是func,不是func_p)

暂且不考虑那么多调用方式(知道就好了),现在回过头来看看

  1. (*(void(*)(void))0x100000)();

  1. ((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处执行的更多相关文章

  1. 让程序跳转到绝对地址0x100000去执行

    网上比较火的一个题,让程序跳转到绝对地址去执行 :可以的实现方式为: ( (void(*)())0x4110e6)(); (*(void(*)())0x4110e6)(); (*((void(*)() ...

  2. 要是想让程序跳转到绝对地址是0x100000去执行

    要对绝对地址0x100000赋值,我们可以用 (unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? *((void (* ...

  3. C语言面试程序阅读整理

    一.数组和指针 1.数组和指针的存储 写出下面的输出结果: char str1[] = "abc"; char str2[] = "abc"; const ch ...

  4. 通过反汇编C语言小程序学习Liunx汇编语言

    大家好!    我是来自山东师范大学的吴乐.    今天在<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...

  5. Linux下简单C语言小程序的反汇编分析

    韩洋原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 写在开始,本文为因为参加MOO ...

  6. 4_PHP流程控制语句_3_程序跳转和终止语句

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. PHP流程控制共有3种类型:条件控制结构.循环结构以及程序跳转和终止语句. 4.3 程序跳转和终止语句 4.3.1 ...

  7. R语言服务器程序 Rserve详解

    R语言服务器程序 Rserve详解 R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大. R语言作为统计学一门语言,一直在小众领域闪耀着光芒.直到 ...

  8. Hybrid App是如何实现网页语言与程序语言的混合?谁占主体?

    [编者按]本文作者@徐珂铭,一位看好Html5的移动互联网的从业人士.喜爱玩技术,会点JAVA.HTML及CSS,有自己的想法及姑且能表达想法的文字,因此有了自己的文章. 基于HTML5的Web Ap ...

  9. windows系统下c语言暂停程序

    原文:windows系统下c语言暂停程序 windows系统下,很多C语言初学者的调试时,往往没看到结果程序就退出了,据我所知的方法主要有以下几种 方法一: #include int main() { ...

随机推荐

  1. @CrossOrigin注解与跨域访问

    在Controller中看到@CrossOrigin ,这是什么?有什么用?为什么要用? what? @CrossOrigin是用来处理跨域请求的注解 先来说一下什么是跨域: (站在巨人的肩膀上) 跨 ...

  2. vue2.0页面缓存和不缓存的方法

    // 模板中: <div class="home"> <keep-alive> <router-view v-if="$route.meta ...

  3. FontAwesome图标选择器

    虽然比较简单,但很实用,在C# MVC下开发,请首先将图标名称保存到数据库中,图标窗口如下. @{ Layout = "~/Views/Shared/_Form.cshtml"; ...

  4. 【bzoj 2049】Cave 洞穴勘测

    Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...

  5. html5 area实例

    真实页面效果:就是一张图 html代码: <!DOCTYPE HTML> <html> <style> body{ padding:0px; margin:0px; ...

  6. pyqt5模块介绍

    python各种库介绍  https://wiki.python.org/moin/GuiProgramming PyQt5.QtWidgets     包含控件 PyQt5.QtGui      图 ...

  7. 结构体类型struct

    教学视频 定义: struct student{CString name; int num; TCHAR sex; int age; };   //注意有个分号 student zansan = {_ ...

  8. 理解JS的执行环境

    执行环境(Execution context,EC)或执行上下文,是JS中一个极为重要的概念 EC的组成 当JavaScript代码执行的时候,会进入不同的执行上下文,这些执行上下文会构成了一个执行上 ...

  9. 第21月第9日 windows下使用vim+ctags+taglist

    1. windows下使用vim+ctags+taglist 最近在公司的同事指导下,学会使用这个东西编写代码,效率提高了不少.所以记录下来,方便大家使用. 1. 下载gvim74.exe文件,并安装 ...

  10. 解决ASP.NET中ServiceStack.Redis每小时6000次访问请求的问题

    1.可以使用3.0的版本: Install-Package ServiceStack.Redis -Version 3.0 2.使用ServiceStack.Redis.Complete: Insta ...