繁体   English   中英

为什么这段代码会编译?

[英]Why does this code compile?

昨晚,太累了,我写了这条奇怪的路线:

::TerminateThread(::TerminateThread, 0);

令我惊讶的是,编译器没有抱怨(它甚至运行...)

由于TerminateThread()被定义为

BOOL WINAPI TerminateThread(HANDLE hThread, DWORD dwExitCode);

我不知道为什么我能编译它。

任何解释?

HANDLE是指向void的指针,Microsoft的编译器允许隐式地将函数指针转换为指向void的指针。

这让我多次绊倒,尤其是堆函数:

HeapAlloc (GetProcessHeap, 0, size); // oops, should be GetProcessHeap()

它接受函数::TerminateThread的地址。 这是类型

BOOL WINAPI (*)(HANDLE, DWORD).

HANDLE定义为

typedef PVOID HANDLE;

因此,编译器编写代码将“函数指针”类型转换为PVOID,这在C ++中完全有效($ 4.10 / 2)

“类型的rvalue”指向cv T的指针,“其中T是对象类型,可以转换为类型为”指向cv void的指针“的rvalue。将”指向cv T的指针“转换为”指针“ “void void”指向T类型对象所在的存储位置的开头,就好像该对象是T类型的派生程度最高的对象(1.8)(即不是基类子对象)。

编辑2:

@dreamlax是正确的。 看来,C ++ 03标准不允许一个函数指针转换为无效*如下所示的程序

void f(){}

int main(){
   void (*p)(void) = f;
   void *p1 = p;
}

我想知道为什么。

真正的答案是:你很幸运。 您可以将三种类型的代码提供给C或C ++编译器:

  • 代码是正确的,其行为由标准或编译器定义
  • 代码完全错误,将被拒绝并出错
  • 代码不够正确,无法定义行为,但不足以被拒绝。

最后一类是“未定义的行为”,是关于C和C ++最糟糕的事情之一。 编译器将接受代码,但很可能不会执行您想要的操作。 将函数指针转换为void指针不是您想要的,并且您可能希望编译器警告您告诉您错误。

这是C ++可能未定义的行为列表 您可以做的最好的事情是尝试调高编译器的警告级别。 在Visual C ++中使用/w3/w4来提高警告级别,它将在编译时捕获更多未定义的行为。 在gcc中,使用-ansi -pedantic -W -Wall将警告级别调高为完全。

我猜HANDLE被定义为void* ,所以任何指针(甚至函数指针)都可以隐式地转换为HANDLE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM