當前位置:首頁 > 公眾號精選 > 嵌入式微處理器
[導讀]1、簡單認識一下void 今天跟大家介紹的知識是C語言中的void關鍵字的用法,void在大部分小伙伴的程序中都只是用于函數無參數傳入,或者無類型返回。 然而我們平時所定義的變量都會有具體的類型,int,float,char等等,那是否有void類型的變量呢?大家可以動手


1、簡單認識一下void

今天跟大家介紹的知識是C語言中的void關鍵字的用法,void在大部分小伙伴的程序中都只是用于函數無參數傳入,或者無類型返回。

然而我們平時所定義的變量都會有具體的類型,int,float,char等等,那是否有void類型的變量呢?大家可以動手實驗一下,答案是:不行,編譯會出錯。


上圖很明顯編譯器不允許定義void類型的變量,變量都是需要占用一定內存的,既然void表示無類型,編譯器自然也就不知道該為其分配多大的內存,于是造成編譯失敗。

雖然void不能直接修飾變量,但是其可以用于修飾指針的指向即無類型指針void*,無類型指針那就有意義了,無類型指針不是一定要指向無類型數據,而是可以指向任意類型的數據。

2、void * 基本操作 

大家其實在使用動態(tài)內存分配的使用就已經遇到了void *的使用,來我們一起看看如下幾個標準函數的原型定義:


    


上面這些函數都是與內存操作有關的函數,可能一些小伙伴使用過也不一定知道每個參數的具體類型是什么,這些void*部分的形參所傳入的實參都是不需要進行強制類型轉化的,所以根本就不需要關注傳入指針所指向的具體類型,然而函數所返回的void *一般都需要通過強制類型轉化為對應的具體類型,除非你最后所傳遞的變量也是void*類型。


參考void*用法:
 1#include <stdio.h>
2#include <stdlib.h>
3#include <malloc.h> 
4
5#define NUM 10
6/*************************************
7 * Fuction:了解一下void*的使用 
8 * Author : (公眾號:最后一個bug) 
9 *************************************/

10int main(int argc, char *argv[]) {
11    int *p1 = (int *)malloc(NUM*sizeof(int)); 
12    int *p2 = (int *)malloc(NUM*sizeof(int)); 
13    int  i = 0;
14
15    //初始化p1 
16    for(i = 0;i < NUM;i++) 
17    {
18        *(p1+i) = i;
19    }
20    //進行內存copy 
21    memcpy(p2,p1,NUM*sizeof(int));
22
23    //輸出另外一個分配的內存 
24    for(i = 0;i < NUM;i++) 
25    {
26       printf("%d,",*(p2+i)); 
27    }   
28    //釋放內存 
29    free(p1);
30    free(p2);
31    return 0;
32}
運行結果:


3、使用void * 實現(xiàn)無類型數據封裝

為了保持文章的完整性,也許這里才是作者最想跟大家介紹的,void*既然如此的靈活一定大有用處,如果僅僅只是用來簡單的傳遞參數似乎有點大材小用,我們得把其用到上層的軟件設計上來。

在一些項目中經常看到有小伙伴把數據類型轉來轉去,甚至有時候為了一個數據類型的變化還得重新寫一個僅僅數據類型不同的函數,這樣的代碼上萬行代碼指日可待,按下面我們以一個例子來跟大家介紹一種辦法能夠減少數據類型變化所帶來的程序重復代碼的增加。

參考實例:


 1#include <stdio.h>
2#include <stdlib.h>
3/********************************** 
4 * Fuction : add
5 * descir :  加法的相關數據及處理辦法 
6 * Author : (公眾號:最后一個bug)
7 **********************************/
 
8typedef struct _tag_Add
9{
10    int a;
11    int b;
12    int result;
13}sAdd;
14
15void Add(void *param)
16{
17    sAdd *p = (sAdd *) param;
18    p->result = p->a + p->b;
19}
20/********************************** 
21 * Fuction : add
22 * descir :  乘法的相關數據及處理辦法 
23 * Author : (公眾號:最后一個bug)
24 **********************************/
 
25typedef struct _tag_Mul
26{
27    float a;
28    float b;
29    float result;
30}sMul;
31
32void Mul(void *param)
33{
34    sMul *p = (sMul *) param;
35    p->result = p->a * p->b;
36}
37
38/************************************* 
39 * Fuction : sCal
40 * descir :  公共的調用接口 
41 * Author : (公眾號:最后一個bug)
42 ************************************/
 
43void sCal(void *param,void *fuc)
44{
45    ((void (*)(void*))fuc)(param);
46}
47
48/********************************** 
49 * Fuction : main
50 * descir : 應用接口實例 
51 * Author : (公眾號:最后一個bug)
52 **********************************/
  
53int main(void)
54{
55    sAdd stAdd;
56    sMul stMul;
57
58    //數據初始化 
59    stAdd.a = 10;
60    stAdd.b = 20;
61
62    stMul.a = 5;
63    stMul.b = 5;
64    //接口直接用 
65    sCal(&stAdd,Add);
66    sCal(&stMul,Mul);
67    //對應的輸出 
68    printf("a + b = %d\n",stAdd.result);
69    printf("a * b = %f\n",stMul.result);
70    printf("公眾號:最后一個bug\n");
71    return 0;
72 } 
運行結果:

分析一下:


    上面的例子可能還是無法完全彰顯void*的強悍之處了,不過其主要的作用就是為了隱藏數據類型,大家也可以理解為一種數據類型的抽象處理,這也是面向對象編程的一種體現(xiàn)。

4、最后小結

對于void這個關鍵字的使用bug菌就先講這么多吧!大家一定要記得對于一些編程技巧一定要嘗試著去使用,可能達到項目目標的方式有很多種,但是一些好的設計不僅僅會讓你的代碼增色不少,同時也會讓同事們覺得你是一個喜歡專研技術的人。


本文授權轉載自公眾號“最后一個bug”,作者未知bug


-END-




推薦閱讀



【01】深度:嵌入式系統(tǒng)的軟件架構設計!
【02】使用git管理嵌入式軟件版本
【03】嵌入式軟件測試的10條秘訣
【04】嵌入式軟件和硬件誰更重要?
【05】嵌入式工程師結合經歷聊硬件工程師和軟件工程師哪個更有前途?


免責聲明:整理文章為傳播相關技術,版權歸原作者所有,如有侵權,請聯(lián)系刪除

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關注更多精彩內容

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
關閉
關閉