簡體   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