这是一个代码,目的是将程序计数器设置为跳转到地址0x1000.我知道它做了什么,但我不明白怎么做.这与我缺乏C语言知识有关.可能你可以赐教.这是声明/功能(我甚至不知道它是什么:))
((void (*)())0x1000)();
Run Code Online (Sandbox Code Playgroud)
我认为它是指向返回void并且不接受任何参数的函数的指针.如果我错了,请纠正我.
axi*_*iac 44
C使用一个简单的规则从内到外解码声明:从标识符开始并在右侧检查[](数组)或()(函数)然后在左侧检查值的类型(存储在数组中或由功能),不越过括号; 从括号中逃脱并重复.
例如:
void (*p)()
Run Code Online (Sandbox Code Playgroud)
p是(右边没有)一个指针(在左边,不要越过括号)到(转义括号,读取下一级)一个函数(右),什么都不返回(左).
当p缺少标识符(在这种情况下)时,剩下的只是一个类型声明.
括在括号中的类型放在值的前面是类型转换.
(void (*)())0x1000
Run Code Online (Sandbox Code Playgroud)
将数字0x1000转换为指向不返回任何内容的函数的指针(请参阅有关上述声明的段落中括号内的内容p).
在下一个级别,上面的表达式(指向函数的指针可以与函数名称一样使用)用于执行指向的代码.
请参阅下面的整个表达式:
(
(
void (*)() /* type: pointer to function that doesn't return anything */
)0x1000 /* value 0x1000 treated as a value of the type declared above */
) /* enclose in parentheses to specify the order of evaluation */
(); /* the pointer above used as a function name to run the code */
Run Code Online (Sandbox Code Playgroud)
Bat*_*eba 17
(void (*)())是一个指向函数的指针,该函数返回void并获取一个未指定但固定的参数.
(void (*)())0x1000被浇铸的字面0x1000上述类型.
最后,函数的后缀() 调用.前面的表达式需要在括号中,否则后缀()将绑定到0x1000语法上无效的.
由你来检查铸件是否真的有效.如果没有,那么程序的行为是不确定的.
Cia*_*Pan 13
一个常数
0x1000
Run Code Online (Sandbox Code Playgroud)
被转换为类型:
(type)0x1000
Run Code Online (Sandbox Code Playgroud)
类型是void (*)()- 一个函数的指针(星号),它不带参数(右边是空括号)(oops,请参阅pmg的注释)并且不返回任何值(void左侧).星号上的其他parens会阻止将其关联void,这会void *在此处错误地创建类型.
所以在演员表之后你有一个指向无参数0x1000的无参数void函数的指针:
(void (*)())0x1000
Run Code Online (Sandbox Code Playgroud)
那个功能......
((void (*)())0x1000)
Run Code Online (Sandbox Code Playgroud)
通过添加空参数列表来调用:
((void (*)())0x1000)();
Run Code Online (Sandbox Code Playgroud)
编写该代码的人应该以可读的方式重写它:
#define ADDRESS_OF_FUNCTION_X 0x1000
typedef void (*func_ptr_t)(void);
...
func_ptr_t function_x = (func_ptr_t)ADDRESS_OF_FUNCTION_X;
function_x();
Run Code Online (Sandbox Code Playgroud)
代码的作用现在几乎都是自我记录的.