c++中的void*


今天看到一段代碼,覺得非常有意思。

void* say_hello(void* args)
{
    cout << "Hello World!" << endl;
    return 0;
}

這里的返回類型竟然是void*。一般來說如果沒有返回值,那么寫一個void就行了,void*到底是什么樣的存在?所以做了一些測試,總結了一些void*指針的用法。

 

1)void*可以指向任何類型的地址,但是帶類型的指針不能指向void*的地址

正常來說如果兩個指針類型不一樣的話,兩個指針變量是不可以直接相等的。例如int* a, float* b,假如令a = b,會直接發生編譯錯誤,而void*指針可以等於任何類型的指針。但是反過來不可以,也就是說一個有類型的指針不能指向一個void*類型的變量(哪怕此時void*變量已經指向了一個有類型的地址)。

    float f = 5.5;
    float* pf = &f;
    void* pv = pf;
    float* pf2 = pv;//編譯錯誤,有類型的指針變量不能指向void*變量

 

2)void*指針只有強制類型轉換以后才可以正常取值

int main(int argc, const char * argv[]) {
    
    float f = 5.5;
    float* pf = &f;
    void* pv;
    
    pv = pf; //這句是可以的
    
    cout<<*pv<<endl;  //編譯錯誤,這樣直接對pv取值是錯誤的
    cout<<*(float*)pv<<endl;  //強制類型轉換后可以取值
    
    return 0;
}

在令pv = pf后,此時pv和pf指向的是同一個地址,值相同,但是兩者的類型是不一樣的。pf作為浮點型指針,是可以直接取到浮點數的,但是pv必須要強制類型轉換以后才可以取值,也就是說一個void*的指針必須要經過強制類型轉換以后才有意義。

int main(int argc, const char * argv[]) {
    
    float f = 5.5;
    float* pf = &f;
    void* pv;

    pv = pf;
   
    cout<<*(float*)pv<<endl;  //強制類型轉換后可以取值,值為5.5
    cout<<*(int*)pv<<endl; //強制類型轉換,值為1085276160
    cout<<(int)(*(float*)pv)<<endl;//取值后再次類型轉換,值為5
    
    return 0;
}

如果把一個指向float*的值的void*指針,強制轉換成int*也是不對的。也就是說地址保存了什么樣的變量,就要轉化成哪種類型的指針,否則就會出錯。

 

3)void*指針變量和普通指針一樣可以通過等於0或者NULL來初始化,表示一個空指針

    void* pv = 0; 
    void* pv2 = NULL;
    cout<<pv <<endl; //值為0x0
    cout<<pv2<<endl; //值為0x0

 

4) 當void*指針作為函數的輸入和輸出時,表示可以接受任意類型的輸入指針和輸出任意類型的指針

void* test(void* a)
{
    return a;
}

int main() {
static int a = 5; int* pi = &a; cout<<pi<<endl; //值為0x100001060 cout<<test(pi)<<endl; //值為0x100001060 cout<<test((void*)pi)<<endl; //值為0x100001060 }

如果函數的輸入類型為void*,在調用時由於是值傳遞,所以函數實際接收到的應該就是一個地址值。這個值可以是任意類型。

int a = 5;
int* pi = &a;

void* test()
{
    return pi; 
}

int main() {
    cout<<test()<<endl;        //值為0x100001060
}

輸出時同樣也是值傳遞,因此可以輸出任意類型指針指向的地址。

 

再讓我們回頭看初始的那段函數:

//返回了一個空指針
void* say_hello(void* args)
{
    cout << "Hello World!" << endl;
    return 0;
}

//沒有返回值
void say_hello(void* args)
{
    cout << "Hello World!" << endl;
   return;
}

其實兩個函數實現的內容是一樣的。但是void*返回類型的函數返回了一個空指針,而void型沒有返回值。

 

總結:

1)void*類型的指針其實本質就是一個過渡型的指針狀態,必須要賦予類型(強制類型轉換)才能正常使用。

2)只能單向類型轉換。void*可以轉化成其他類型,但是有類型的不能轉化成void*。

2)在函數調用過程中的使用作為輸入輸出參數也非常好用,可以靈活使用任意類型的指針,避免只能使用固定類型的指針。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM