精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何理解C++中的void?

jf_78858299 ? 來源:小余的自習室 ? 作者:小余的自習室 ? 2023-03-30 15:01 ? 次閱讀

1.定義

首先void*中的void代表一個任意的數據類型,"星號"代表一個指針,所以其就是一個任意數據類型的指針。

對于指定數據類型的指針如int* ,double*等,他們的sizeof都是4個字節,因為都是一個指針,只是指針指向的數據類型不一致。

C語言是一個強類型的語言, 那么他們之間有什么區別呢 ?前面一篇文章我們說過, 指針+1和-1是和指向數據類型有關的

假設指針值為0x00000001,指針類型為int類型,整數為n,則計算出來的結果為0x00000001+ n乘以4,這里的4是因為指針類型為int,如果是double,則為0x00000001+ n乘以8. 所以我們使用double類型指針+1,地址移動了8位,而用int指針+1,地址移動了4位,就是這個道理。

這說起來其實和數據內存對齊有關。你可以把這里的4和8理解為跳躍力。

那對于void*呢? 其實就是一個未指定跳躍力的指針

那void*的跳躍力又什么時候指定?在需要使用的時候指定就可以了,好處: 可以實現泛型編程,節省代碼 。

2.void*使用場景

2.1:當函數傳參時不確定數據類型時或者支持多種數據類型傳遞時。

代碼如下:

void say(int type,void* pArgs) {
    switch (type) 
    {
        case 0:
        {
            double* d = (double*)pArgs;
            break;
        }   
        case 1:
        {
            int* i = (int*)pArgs;
            break;
        }       
    }
}

該函數使用一個type來表示當前參數void*的類型,內部通過type判斷轉換的類型。

2.2:函數返回值不需要考慮類型,只關心返回的大小。

如malloc函數:

原型:

void* malloc(size_t size)

代碼使用:

int* a = nullptr;
double* b = nullptr;
b = (double*)malloc(sizeof(double));
a = (int*)malloc(sizeof(double));

可以看到malloc返回值類型為void*,其只返回分配內存的大小,不關心分配后的內存你是使用int還是double類型進行劃分.

注意:函數外部在接收到void*格式的返回值時,需要強轉為自己的數據類型才能使用。

3.void*使用中的注意點:

1.使用賦值運算符“=”時,void*只能作為左值不能作為右值。

void*作為一個未指定數據類型的指針,可以指向任何一個數據類型的指針,但是有數據類型的指針,不能指向一個void* 的指針。

代碼如下:

int i = 5;
int* pi = &i;
void* pv = pi;
int* pi1 = pv;//編譯錯誤,void*類型的指針不能初始化為指定類型的指針

這其實是可以理解的:

假設void*指定了一個非int類型的數據,如果此時賦值給int*類型的指針,則會發生嚴重的bug**。

2.void*類型必須強轉為指定類型的數據才能使用。

void 在未指定類型的情況下,是不能直接使用的, 只有在轉換為顯示類型后才能使用 。 *

代碼如下:

int i = 5;
int* pi = &i;
void* pv = pi;
//cout << *pv << endl;//表達式必須是指向完整對象類型的指針
cout << *(int*)pv << endl;

代碼中可以看出在未強轉為顯示類型前,使用void*會報表達式必須是指向完整對象類型的指針.

說明void*一定要強轉后才能使用.

沒有強轉的void*是沒有意義的。

那可能有同學要問了,假設我們并不知道當前void*數據類型,強轉錯誤了會發生什么事。

int i = 5;
int* pi = &i;
void* pv = pi;

cout<<"(int*)pv:" << (int*)pv << endl;
cout<<"(double*)pv:" << (double*)pv << endl;
cout <<"*(int*)pv:" << *(int*)pv << endl;
cout <<"*(double*)pv:" << *(double*)pv << endl;

運行結果:
(int*)pv:0043F724
(double*)pv:0043F724
*(int*)pv:5
*(double*)pv:-9.25596e+61

此時可以看到雖然pv強轉為double后,指針指向的地址和強轉為int類型指針指向地址是一樣的都是0x0043F724。但是取值后就發生了異常,因為double占用的是8個字節,所以取值的是后8位字節,所以取到的是一個錯誤的值,實際只有4個字節是有效的。

我們在使用void*強轉的時候一定要注意這點 、

3.C++中使用(void*)0表示空指針。

在C語言中空指針定義方式:

#define NULL ((void*)0)

在C++語言中:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else 
        #define NULL ((void*)0)
    #endif
#endif
可以看到在C語言中NULL代表(void*)0,而在C++中NULL代表的是0,使用nullptr來表示(void*)0空指針,
所以在C++中推薦使用新標準的nullptr來初始化一個空指針。

4.當void*作為函數的參數類型或者返回值類型時,說明該函數可以接收或者返回任意類型的指針。

代碼如下:

void* _say(void* pArgs) {
    return pArgs;
}
int  main()
{
    int _a = 5;
    float f = 10.8;
    int* _pi = &_a;
    float* pf = &f;

    cout << *(int*)_say(_pi) << endl;
    cout << *(float*)_say(pf) << endl;

}
運行結果:
5
10.8

代碼中可以看出參數void* pArgs可以使用任意類型的實參,返回值也可以返回任意類型的指針,但是最終需要轉換為具體類型才能使用。

void*在C++中的作用其實就是為了實現泛型編程,和Java中使用Object來表示是一樣的,所以又稱為通用指針和泛指針,不過 C++中大部分情況下會使用模板編程來實現泛型

上面_say函數代碼可以使用下面模板函數代替:

T _say(T t) {
    return t;
}

區別在于: 模板編程不需要將強制轉換為具體類型 ,其使用方式如下:

int _a = 5;
float f = 10.8;
int* _pi = &_a;
float* pf = &f;

cout <<*_say(_pi) << endl;
cout << *_say(pf) << endl;

未強轉也可以直接得出結果,這是因為模板編程會在編譯器幫我們生成具體的函數。

調用了兩次_say會分別實現:

float* _say(float* t) {
    return t;
}
int* _say(int* t) {
    return t;
}

所以運行的時候是調用了不同的函數,而使用void*的泛型只調用一個函數。

總結

  • 1.void*是一個過渡型的指針狀態,可以代表任意類型的指針,取值的時候需要轉換為具體類型才能取值。其是處于數據類型頂端的狀態:

    圖片

  • 2.void* 使用賦值運算符“=”賦值時,只能將具體類型賦值給void星,不能將void*賦值給具體類型。

  • 3.void*一般作為參數或者返回值來實現泛型編程,但是C++中一般考慮使用模板編程來實現。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    6898

    瀏覽量

    88834
  • C++
    C++
    +關注

    關注

    22

    文章

    2104

    瀏覽量

    73497
  • void
    +關注

    關注

    0

    文章

    23

    瀏覽量

    9857
收藏 人收藏

    評論

    相關推薦

    C++的結構和類

    C++ 仍然是嵌入式開發的少數??語言,但當項目變得太大而無法有效使用 C 時,開發人員通常會采用 C++。這些開發人員通常從 C 過渡到 C++
    發表于 07-18 17:37 ?792次閱讀

    C語言和C++那些不同的地方

    ++11標準。根據不同的標準,它們的功能也會有所不同,但是越新的版本支持的編譯器越少,所以本文在討論的時候使用的C語言標準是C89,C++標準是C++99.我們來介紹
    的頭像 發表于 12-07 14:29 ?908次閱讀
    <b class='flag-5'>C</b>語言和<b class='flag-5'>C++</b><b class='flag-5'>中</b>那些不同的地方

    void(*isr)(void)__irq怎么理解

    void(*isr)(void)__irq怎么理解,求高手指教!
    發表于 08-10 14:12

    C++筆記003:C++從一個小程序開始

    ,暫且這樣理解。<<這個左移操作符,我們發現已經“變味”了,在C++里面已經進行功能的改造,跟以前C語言的左移操作符用法不一樣了,這就是C++
    發表于 03-05 12:51

    C++筆記004:C++類通俗點說—— C結構體復習

    的程序設計,對象具有屬性(狀態)和行為,屬性保存在成員變量,行為通過成員方法(函數)來實現。成員方法又是什么?其實方法和函數可以理解為一回事。只是在C++
    發表于 03-05 12:53

    如何把C++的源程序改寫成C語言

    加一八零二五二六七六九二(微信)方法有兩種:第一種是將C++的面向對象特征去掉,先全部理解源代碼的邏輯,然后改寫;第二種是在C中保留面向對象的部分特征,用結構體實現類的功能。第一種方
    發表于 07-05 14:59

    C/C++程序員實用大全配套代碼

    CC++程序員實用大全》配套代碼  [涉及平臺] VC++ [作者] void [文件大小] 629KB  [更新日期] 2005-10-28
    發表于 02-09 11:18 ?28次下載

    C語言voidvoid指針深層探索

    1.概述 本文將對void關鍵字的深刻含義進行解說,并詳述voidvoid指針類型的使用方法與技巧。 2.void的含義 void的字面意
    發表于 09-21 11:36 ?166次下載

    EE-128:C++的DSP:從C++調用匯編類成員函數

    EE-128:C++的DSP:從C++調用匯編類成員函數
    發表于 04-16 17:04 ?2次下載
    EE-128:<b class='flag-5'>C++</b><b class='flag-5'>中</b>的DSP:從<b class='flag-5'>C++</b>調用匯編類成員函數

    淺析C++this指針的理解以及作用

    01 C++程序到C程序的翻譯 想要理解C++語言中的this指針,下面我們做一個舉例,我們要先把下面的C++代碼轉換成
    的頭像 發表于 06-27 11:24 ?2901次閱讀
    淺析<b class='flag-5'>C++</b><b class='flag-5'>中</b>this指針的<b class='flag-5'>理解</b>以及作用

    C++如何用虛函數實現多態

    01 — C++虛函數探索 C++是一門面向對象語言,在C++里運行時多態是由虛函數和純虛函數實現的,現在我們看下在C++如何用虛函數實現
    的頭像 發表于 09-29 14:18 ?1672次閱讀

    C++的Edison IoT黑盒

    電子發燒友網站提供《C++的Edison IoT黑盒.zip》資料免費下載
    發表于 10-21 14:20 ?0次下載
    <b class='flag-5'>C++</b><b class='flag-5'>中</b>的Edison IoT黑盒

    C++struct和class的區別?

    C++struct和class的區別是什么?C++struct和class的最大區別在于: ? ? ? ? struct的成員默認是公有的, 而class的成員默認是私有的,
    的頭像 發表于 03-10 17:41 ?742次閱讀

    C++簡史:C++是如何開始的

    的 MISRA C++:2023 博客系列的第二部分。 在這篇博客,我們將深入探討 C++ 的歷史、編程語言多年來的發展歷程以及它的下一步發展方向。
    的頭像 發表于 01-11 09:00 ?538次閱讀
    <b class='flag-5'>C++</b>簡史:<b class='flag-5'>C++</b>是如何開始的

    C++實現類似instanceof的方法

    函數,可實際上C++沒有。但是別著急,其實C++中有兩種簡單的方法可以實現類似Java的instanceof的功能。 在 C++
    的頭像 發表于 07-18 10:16 ?534次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>中</b>實現類似instanceof的方法