簡體   English   中英

函數為什么接受空指針?

[英]Why does a function accept a void pointer?

我想了解pthread。

但是,需要按以下方式創建線程方法:

void *SomeMethod(void* x)
{
    //Do Something
}

為什么必須創建一個接受void指針的函數? 我們不能將pthread與這樣的函數一起使用嗎?

void SomeMethod()
{
}

因為pthread_create函數接受類型為void* (*)(void*)的參數,該參數是一個接受void*並返回void*的函數,所以需要使用pthread_create創建線程。

pthread_create API可以通過它來允許您將數據傳遞到新線程並再次獲取數據。 如果您不想傳遞任何內容,則仍然必須滿足該接口,只需將其傳遞為NULL。

僅僅因為現在不希望將任何參數傳遞給新線程並不意味着該API應該設計為僅支持當前用例。 就使用void* (可以將其傳遞為NULL)的函數編寫API而言,相對於不帶任何參數並要求用戶提出自己的解決方案來傳遞數據的函數而言,具有更好的API效果到新線程。

在C ++中,您可以對新線程使用任何類型的函數,並將其傳遞給所需的任何參數:

std::thread t(&SomeMethod);

因為他們只想編寫一個用於創建線程的函數-接收和返回數據。

否則,他們將不得不至少寫出四種可能性。

您可以自由地忽略輸入參數和返回值。

只是一個簡單的問題

根據pthread_create()手冊頁 ,我們可以看到,該函數的簽名為

 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
               void *(*start_routine) (void *), void *arg);

第三個參數的類型

void *(*start_routine) (void *)

這意味着,它期望指向返回類型為void *並接受void *參數的函數的指針。 因此,我們需要相應地定義線程函數。

就是說,關於在參數傳遞中使用void指針,引用C11 ,第6.3.2.3章。

指向void的指針可以與任何對象類型的指針進行轉換。 指向任何對象類型的指針都可以轉換為void指針,然后再返回; 結果應等於原始指針。

如我們所見, void指針用於將任何類型的數據傳遞給線程函數,前提是將其轉換回函數內部的實際類型。

同樣,FWIW,請勿嘗試偏離標准明確規定的功能指針的要求簽名

[....]如果使用轉換后的指針來調用其類型與引用的類型不兼容的函數,則該行為是不確定的。 如果您不想(不需要)傳遞任何有效的參數值,則可以始終傳遞NULL

因為很多時候,我們想給線程一些東西(可以使用,也可以關閉)。 一個非常典型的示例是傳入一個類的實例,因此您可以調用該類的成員函數。

但這可能是各種各樣的事情-結構或指向一些簡單數據的指針。

當然,使用std::thread仍然會隱藏大多數此類內容,您無需擔心。 我強烈建議一般使用std::thread代替pthread

void *SomeMethod(void* x)用作新線程的入口點。 如果要向新線程傳遞一些數據(結構,緩沖區,正則整數等),應該怎么做? 特別是對於此入口點方法,它會接收void*參數,該參數可以指向您想要的任何內容。 然后,可以在函數體內將其強制轉換回正確的類型,並由輔助線程使用它。

如果您的線程不需要任何其他數據,則可以向其傳遞NULLnullptr (對於C ++ 11)。

不,您建議的方法簽名不能用作pthreads線程的啟動函數。 如果將指向此類函數的指針傳遞給pthread_create()則編譯器應發出警告。 如果運行結果程序,則將調用未定義的行為,因為指針的類型不正確。 實際上,pthreads庫將嘗試將參數傳遞給start函數,並期望從中返回一個值。 如果您提供一個指向既不消耗參數也不返回值(均屬於適當類型)的函數的指針,則程序很可能崩潰。

至於為什么要求啟動函數具有它的簽名,可以使用void *參數傳遞任何類型的實際參數,包括包含多個不同值的復合類型,並且類似地, void *返回類型可以是用於傳達任何類型的返回值。 這幾乎是最通用的功能類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM