((void(*)())0)() 这个宏的含义是什么?

4
以下宏的结果是明确的:
#define CRASH() do {\
  *(int *)(uintptr_t)0xbbadbeef = 0;\
  ((void(*)())0)();\
} while (false)

我的问题是,这行代码的含义是什么:

((void(*)())0)();

“break down to”在英语中是什么意思?例如,“这是一个返回指向...的指针的函数”。

1
http://www.youtube.com/watch?v=Q75MZws4ltw#t=1m27s - Karoly Horvath
2
在C和C++中,这个表达式有不同的含义。在C中,空括号表示一个函数接受未指定但固定数量的参数。而在C++中,它们表示一个不接受任何参数的函数(类似于C中的fx(void))。 - pmg
@Ed heal: 这种爬虫崩溃的方式没有错。有时候,一个人可能有理由不调用exit()、_exit()或abort()。而且,在某些平台/场合下,解引用deadbeef指针不会导致崩溃/异常,所以第三行 可能 仍然有用。 - wildplasser
1
@Ed Heal:信号可能无法使用、被屏蔽或不需要。也许宏必须能够从信号处理程序中调用。谁知道呢?顺便说一句:如果有调试器+监视点可用,设置一个监视点在0xdeadbeef上将是一个万能的方法,堆栈跟踪希望能做到其余的事情。此外:使用调试器,有可能跳出这个片段并继续执行。你无法从abort()中逃脱。 - wildplasser
1
由于你不知道上下文(我也不知道),所以你无法证明是否存在更好的方法。可能有,也可能没有。另外,上面的代码并不难读。即使你不理解它是如何工作的,你仍然可以阅读它,并知道它做了什么(或者应该做什么)。你理解你的调试器源代码吗? - wildplasser
显示剩余9条评论
9个回答

14

看起来它将0转换为函数指针(其签名不需要参数且返回类型为void),然后调用该函数。

(     (            void(*)()                  ) 0       )      ();
  /* cast..*/ /* fn pointer signature */  /*..cast 0 */  /* invocation */

这句话的另一种说法是,它试图调用一个函数,该函数应该位于内存地址0x00000000处,而这个地址保证是无效的。


3
  • 0强制转换为指向不带参数的void函数的指针 (表达式中的(void(*)())0)
  • 通过一个空参数列表的指针调用该函数 (在其后面加上())。

EDIT 1: 根据Cristoph的评论进行了编辑。


2
C vs C++又一次引发争议:在C++中,空参数列表意味着函数不带参数;而在C中,只有对于定义才是这样 - 通常,空参数列表意味着该函数接受未指定数量的非变参参数,受默认参数提升影响。 - Christoph
@Christoph 真糟糕!不过至少在这种情况下,修正答案所需的工作量要少得多。 - Sergey Kalinichenko

2
它将0转换为函数指针,该函数不带参数并返回void,然后尝试调用此函数。它基本上是对空指针进行解引用。

2
它将一个指向 NULL 的指针转换为一个不带参数且返回值为 void 的方法,并尝试调用此方法。
毫无疑问,程序会崩溃,因此名称 CRASH 非常贴切。

0

对我来说,将其翻译成另一种C++语言比直接翻译成英语更简单。

typedef void (void_func_t)();       // type of a function taking no arguments 
                                    // and returning void
typedef void_fnct_t* void_func_ptr; // pointer to such a function
static_cast<void_func_ptr>(0)();    // call that function
// ((void_func_ptr)0)();            // pure C equivalent cast

静态转换不会抛出异常并防止程序崩溃吗? - Lundin
@Lundin:static_cast 从不 抛出异常。dynamic_cast 可能会抛出异常,但它不能与函数指针一起使用,并且仅在转换引用时才会抛出异常。 - David Rodríguez - dribeas

0

它将0转换为函数指针,然后尝试调用该函数。这将导致段错误和崩溃。

编辑:这些问题的竞争太激烈了。给大家点赞,我要去睡觉了 :)


0

它的意思是“将NULL指针视为指向void function()的指针,调用function()”。


0

它将值零取出,并将其转换为不返回任何内容(void)的函数指针。

据推测,其目的是当您调用此“函数”时,它会调用地址零,这确实会导致应用程序崩溃。


0
如果fp是一个指向函数的指针,那么*fp就是函数本身,所以(fp)()是调用它的方式。ANSI C允许将其缩写为fp(),但请记住这只是一种缩写。-------C陷阱与缺陷。 ( ( void()() )0 ) () 是 ( ( void()() )0 )() 的缩写。

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