复杂的C语言类型转换解释

8

我正在试图弄清楚以下C语言代码的作用:

((void(*)())buf)();

'buf'是一个char数组。


5
寻找一个名为"cdecl"的程序。下载它。将声明粘贴进去。你将受益匪浅。 - Paul Tomblin
@Paul:我会尝试一下,希望它不会让我的机器崩溃! - Tony The Lion
1
这段代码可能会出现在JIT中,或者在操作系统的动态链接器/加载器中。正如其他人所说,这是可怕的东西,但只有在典型应用程序中遇到它时才会感到可怕。在适当的位置使用它,它并不可怕,只是困难的东西。 - Steve Jessop
10个回答

21

让我们一步一步来。

void(*)()

这是一个指向函数的指针,该函数接受未指定参数且没有返回值。

(void(*)())buf

将buf简单地转换为这个函数指针类型。最后,

((void(*)())buf)();

调用这个函数。

因此,整个语句的意思是“将buf解释为一个不带参数的void函数指针,并调用该函数。”


3
将字符缓冲区转换为函数并调用它是不好的。这么做要么是试图进行自修改代码,要么是恶意意图执行某种利用。无论哪种情况,务必避免使用。 - Paul Tomblin
@Nick Meyer:你说得对,已经修复了。 @pmg:那个也已经修复了。我相信你的话,但是你有参考资料吗? 谢谢你们两位。 - Thomas
4
注意,C语言不能保证数据指针和函数指针具有相同的大小。 - David Nordvall
@Thomas:在n1401.pdf中的最新草案中,第6.5.2.2/6节。没有参数的函数声明不提供原型;void(*)()就是这样的声明。 - pmg
4
除了指针大小之外,C语言不能保证在堆栈或堆上分配的内存是可执行的。该代码应仅出现在JIT或等效环境中,并且必须是特定于平台的。假设buf刚刚被填充了机器指令,则引用的强制类型转换和调用之前的那一行可能应该是某种特定于平台的操作以刷新icache。 - Steve Jessop
显示剩余5条评论

9
它将buf转换为类型为void(*)()的函数指针(返回void且参数未指定的函数),并调用它。
ANSI标准实际上不允许将普通数据指针转换为函数指针,但您的平台可能允许这样做。

你怎么能将数组转换为函数指针?有没有一篇文章可以解释一下? - Tony The Lion
指针只是像任何其他值一样的字节集合(因此可以在C中表示为char数组)。您可能会发现,在程序的其他地方,已经执行了相反的操作:char *buf = (char *)function;或类似的操作。 - Wernsey
你可以做到这一点是因为它是 C 语言 - 你可以做任何你想做的事情。虽然这是一个可怕的想法,但你确实能做到。 - Clyde
1
我想说的是,它不能保证工作。在 ANSI 中,这是未定义的行为:在哈佛架构中,程序内存和数据内存是物理上分离的,因此从 char*void(*)() 的转换是没有意义的。 - Wernsey
即使在冯·诺伊曼体系结构上,如果正在使用分段,则具有相同值的数据指针和函数指针可能指向不同的内存(MS-DOS“Small”内存模型是一个真实的例子)。 - caf

5

当我遇到令人费解的声明时,我倾向于使用 "cdecl" 命令。例如:

[me@machine]$ cdecl
Type `help' or `?' for help
cdecl> explain (void(*)())buf
cast buf into pointer to function returning void

虽然有些情况下我希望有一个工具能解释 "cdecl" 的输出 :/


4

这将buf强制转换为void (*)()类型,即一个不确定参数且返回空值的函数指针。然后它在该地址调用该函数(最右边的两个括号)。


2

它将buf转换为一个函数指针,该指针接受未指定的参数并调用它。


2
((void(*)())buf)(); \------------/ 将 `buf` 转换为 \---------/ 类型:指向一个接受固定但未指定数量的参数并返回 void 的函数的指针 \----------------/ 并调用该“函数”

+1 你关于参数数量未指定的观点是正确的。如果你能举个例子来说明,你可能会得到更多人对你洞察力的赞赏 :) - Andomar

1
我猜在很多情况下,它会导致机器崩溃。否则,它将把数组视为返回void的函数指针并调用它。

1

1

有一个在线版本的 'cdecl' 工具,lsc提到过它,你可能会发现它很有用:http://www.cdecl.org/


0

该函数没有任何参数。该函数类型具有未指定的参数。 - Steve Jessop
鉴于其他回答,我将保留文章不变。 - segy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接