C語言使用void *類型作為函數傳參

C語言使用void *怎么理解:

根據本人的理解,他就是指向操作數據區的首地址而已

凡是void指的數據區都要進行第二次初始化數據類型(即dtype p=(dtype)pdata)*。
舉兩個例子:

傳入函數:

void tx_data(void *pdata)
{int* p=(int*)pdata;//第二次初始化//接下來對p操作}

傳出函數:

static int data
void* rx_data(void )
{return &data;
}
//使用void *
int* p=(int*)rx_data();  //第二次初始化
//接下來對p操作

隱藏數據類型使用void*,就是這么簡單,不要跟什么抽象掛鉤,什么無類型就是任意類型,這種理解都是錯的,完全是愚弄人
用void的好處:
1.隱藏數據類型,傳參讓別人不知傳的啥,有保密的作用
2.隱藏數據類型,象元編程一樣,等數據傳過來再識別,再操作,可以簡化代碼,讓代碼輸入量抽象起來,
3.隱藏數據類型,等數據傳過來再識別,再操作,方便給用戶堆代碼,象linux操作系統的驅動程序都是用void
來給你堆
代碼,這樣可以讓有限的代碼轉換無限的經濟價值
4.隱藏數據類型,你在做各種通訊收發程序時,代碼可以重用度高,修改方便,上面的int換成多個stuct的拼接嵌套就可以寫出很復雜的程序

后面搞一簡單的練兵,void*是隨你寫程序的功力對他的認識逐步提升的,菜鳥不用急,不積跬步無以至千里

典型的如內存操作函數memcpy和memset的函數原型分別為:

void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );

這樣,任何類型的指針都可以傳入memcpy和memset中,這也真實地體現了內存操作函數的意義,因為它操作的對象僅僅是一片內存,而不論這片內存是什么類型。如果memcpy和memset的參數類型不是void *,而是char *,那才叫真的奇怪了!這樣的memcpy和memset明顯不是一個“純粹的,脫離低級趣味的”函數!

下面的代碼執行正確

memset接受任意類型指針

int intarray[100];
memset ( intarray, 0, 100*sizeof(int) ); //隱藏數據類型byte的字節操作 第二次初始化

memcpy接受任意類型指針

int intarray1[100], intarray2[100];
memcpy ( intarray1, intarray2, 100*sizeof(int) ); //隱藏數據類型byte的字節操作 第二次初始化

使用枚舉定義隱藏數據類型

enum datatype{//枚舉出來的都是常量,首字母大寫,且作用域為整個main函數_Char,_CharArr,_Int,_Float
};
//使用結構體定義一些數據
struct demo{char a;char stringArray[100];int number;float score;}DEMO;//使用枚舉定義數據結構體數據類型長度
enum datalegth{//此處為了方便觀察就不使用首字母大寫_aLEN = sizeof(char),_stringArrayLEN = 20 * sizeof(char),_numberLEN = sizeof(int),_floatLEN = sizeof(float)
};

測試函數聲明

int test(void *data,enum datatype type,int datalength);

測試函數實現

int test(void *data,enum datatype type,int datalength){switch(type){//第二次初始化case _Char:{//char *convertData = (char *)malloc(sizeof(char *));//_Char:后面接的是完整語句,不能出現聲明,有兩種解決辦法,一種是在冒號后加分號,但這里是switch中,需要用大括號括起來(代碼塊,聽說源于lisp)char *convertData = data;//將void *類型賦值給 char *類型char char1 = *convertData;printf("its a char: %c\n",char1);// free(convertData);break;}case _CharArr:{char *convertData = data;char charArr[datalength];strcpy(charArr,convertData);printf("its a string :%s\n",charArr);break;}case _Int:{int *number = data;printf("its a number:%d\n",*number);break;}case _Float:{float *convertData = data;printf("its a float:%f\n",*convertData);break;}}return 0;//為了便于添加功能,這里暫時留著
}

結構體變量賦值

DEMO.a = 'A';strcpy(DEMO.stringArray,"this is DEMO string variable");//strcpy有一個問題,只管復制進去的,但之前結構體中數組并未初始化可能導致后續//字符出現"粘連"如ble后面不是\0,而是之前堆棧棄用的內存空間的一些垃圾值// DEMO.array = "this is DEMO struct variable";//數組只有在初始化時才能這樣賦值,之后通過遍歷寫入,或者strcpy進去DEMO.number = 88;DEMO.score = 100.0;
//使用結構體指針
struct demo *pDemo = NULL;//指針需要初始化,否則隨機指向不可讀寫的內存區域,后續無法修改指針變量。
pDemo = &DEMO;
//函數調用
test(&(pDemo->a),_Char,_aLEN);  第二次初始化
test(&(pDemo->stringArray),_CharArr,_stringArrayLEN);
test(&(pDemo->number),_Int,_numberLEN);
test(&(pDemo->score),_Float,_floatLEN);
最終代碼
#include <stdio.h>
#include <string.h>
#include <stdlib.h>enum datatype{//枚舉出來的都是常量,首字母大寫,且作用域為整個main函數_Char,_CharArr,_Int,_Float
};enum datalegth{//此處為了方便觀察就不使用首字母大寫_aLEN = sizeof(char),_stringArrayLEN = 100 * sizeof(char),_numberLEN = sizeof(int),_floatLEN = sizeof(float)
};int test(void *data,enum datatype type,int datalength);int main(int argc,char const argv[]){struct demo{char a;char stringArray[100];int number;float score;}DEMO;DEMO.a = 'A';strcpy(DEMO.stringArray,"this is DEMO string variable");//strcpy有一個問題,只管復制進去的,但之前結構體中數組并未初始化可能導致后續的字符出現"粘連"如ble后面不是\0,而是之前堆棧棄用的內存空間的一些垃圾值// DEMO.array = "this is DEMO struct variable";//數組只有在初始化時才能這樣賦值,之后通過遍歷寫入,或者strcpy進去DEMO.number = 88;DEMO.score = 100.0;struct demo *pDemo = NULL;//指針需要初始化,否則隨機指向不可讀寫的內存區域,后續無法修改指針變量。int length = sizeof(struct demo *);//結構體指針大小printf("length is %d\n",length);// pDemo = (struct demo *)malloc(sizeof(struct demo *));// if(pDemo == NULL) printf("分配內存失敗!\n");//如果未分配內存     //malloc是分配內存塊,C語言的變量名,函數名皆為符號,符號不占用空間,所以將通過malloc獲取的內存空間,賦值給指針,實質上是賦值該內存塊的首地址給指針,malloc有一個特性,不會將分配的內存塊上的數據擦洗掉!!pDemo = &DEMO;printf("-------\n");test(&(pDemo->a),_Char,_aLEN);test(&(pDemo->stringArray),_CharArr,_stringArrayLEN);test(&(pDemo->number),_Int,_numberLEN);test(&(pDemo->score),_Float,_floatLEN);// free(pDemo);puts("finished prosess");return 0;
}int test(void *data,enum datatype type,int datalength){switch(type){//第二次初始化case _Char:{//char *convertData = (char *)malloc(sizeof(char *));//_Char:后面接的是完整語句,不能出現聲明,有兩種解決辦法,一種是在冒號后加分號,但這里是switch中,需要用大括號括起來(代碼塊,聽說源于lisp)char *convertData = data;//將void *類型賦值給 char *類型char char1 = *convertData;printf("its a char: %c\n",char1);// free(convertData);break;}case _CharArr:{char *convertData = data;char charArr[datalength];strcpy(charArr,convertData);printf("its a string :%s\n",charArr);break;}case _Int:{int *number = data;printf("its a number:%d\n",*number);break;}case _Float:{float *convertData = data;printf("its a float:%f\n",*convertData);break;}}return 0;//為了便于添加功能,這里暫時留著
}

簡單的void* 返回int* 類型的函數和一個返回char* 類型的函數

#include <stdlib.h>
#include <stdio.h>
void reInt(int);
void* reIntp(int*);
void* reChar(char*);
int main()
{int num=10;int *nump;char str[10]="CSDN";char* strp;reInt(num);nump = (int*) reIntp(&num); //強制類型轉化不能忘!隱藏數據類型  第二次初始化strp = (char*)reChar(str); //強制類型轉化不能忘! 隱藏數據類型  第二次初始化printf("主函數輸出:%d\n",*nump);printf("主函數輸出:%s\n",strp);return 0;
}
//一般返回類型的函數
void reInt(int a)
{printf("void返回類型的函數的輸出:%d\n",a);return; // 沒有返回值
}
//void*返回類型的函數 返回int*
void* reIntp(int *a)
{printf("void*返回類型返回int*的函數的輸出:%d\n", *a);return a; // 返回 int *隱藏數據類型
}
//void*返回類型的函數 返回char*
void* reChar(char* str)
{printf("void*返回類型返回char*的函數的輸出:%s\n",str);return str;隱藏數據類型
}

void*函數的返回值類型struct

struct MyStruct {int a;char b;double c;
};void* get_struct() {struct MyStruct* s = malloc(sizeof(struct MyStruct));s->a = 1;s->b = 'b';s->c = 3.0;return s;
}int main() {struct MyStruct* s = (struct MyStruct*)get_struct();  第二次初始化printf("a: %d, b: %c, c: %f\n", s->a, s->b, s->c);free(s);return 0;
}

創作不容易,如果對您有幫助,請多打賞!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38182.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38182.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38182.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Sparse4D v3: Advancing End-to-End 3D Detection and Tracking

Sparse4D v3: Advancing End-to-End 3D Detection and Tracking 相關內容&#xff1a;總覽&#xff0c;Sparse4D v1&#xff0c;Sparse4D v2&#xff0c; 單位&#xff1a;地平線(Sparse4D v1 v2 原班人馬) GitHub&#xff1a;https://github.com/HorizonRobotics/Sparse4D …

昇思25天學習打卡營第5天 | 網絡構建

目錄 1.定義模型類 2.模型層 nn.Flatten nn.Dense nn.ReLU nn.SequentialCell nn.Softmax 3.模型參數 代碼實現&#xff1a; 總結 神經網絡模型是由神經網絡層和Tensor操作構成的&#xff0c; mindspore.nn提供了常見神經網絡層的實現&#xff0c; 在MindSpore中&a…

啟動spring boot項目停止 提示80端口已經被占用

可能的情況: 檢查并結束占用進程: 首先,你需要確定哪個進程正在使用80端口。在Windows上,可以通過命令行輸入netstat -ano | findstr LISTENING | findstr :80來查看80端口的PID,然后在任務管理器中結束該進程。在

AI智能客服項目拆解(1) 產品大綱

本文作為拆解AI智能客服項目的首篇&#xff0c;以介紹產品大綱為主。后續以某AI智能客服產品為例&#xff0c;拆解相關技術細節。 AI智能客服是一種基于人工智能技術的客戶服務解決方案&#xff0c;旨在提高客戶滿意度和優化企業運營。利用人工智能和自然語言處理技術&#xff…

MySQL之索引失效的情況

什么情況下索引會失效&#xff1f; 違反最左前綴原則范圍查詢右邊的列不能使用索引不要在索引列上進行運算操作字符串不加單引號導致索引失效以%開頭的like模糊查詢 什么情況下索引會失效&#xff1f; 示例&#xff0c;有user表如下 CREATE TABLE user (id bigint(20) NOT NU…

實驗1 多層感知器設計(MLP)

1.實驗目的 掌握多層感知器的原理。掌握多層感知器的設計、訓練和測試。2.實驗要求 設計一個多層感知器,用于對給定的數據進行分類。要求代碼格式規范,注釋齊全,程序可正常運行。 3.模型設計 實驗設計一個多層感知機,三層機構,只含一個隱藏層,輸入層,隱藏層,輸出層 1…

JAVA期末速成庫(11)第十二章

一、習題介紹 第十二章 Check Point&#xff1a;P454 12.1&#xff0c;12.9&#xff0c;12.10&#xff0c;12,12 二、習題及答案 12.1 What is the advantage of using exception handling? 12.1使用異常處理的優勢是什么? 答:使用異常處理有以下優勢&#xff1a; 1. 提高…

C++ 模板類的示例-數組

類模板可以有非通用類型參數&#xff1a;1&#xff09;通常是整型&#xff08;C20標準可以用其它的類型&#xff09;&#xff1b;2&#xff09;實例化模板時必須用常量表達式&#xff1b;3&#xff09;模板中不能修改參數的值&#xff1b;4&#xff09;可以為非通用類型參數提供…

Android中使用performClick觸發點擊事件

Android中使用performClick觸發點擊事件 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將探討在Android開發中如何使用 performClick() 方法來觸發點擊…

數據庫-python SQLite3

數據庫-python SQLite3 一&#xff1a;sqlite3 簡介二: sqlite3 流程1> demo2> sqlite3 流程 三&#xff1a;sqlite3 step1> create table2> insert into3> update4> select1. fetchall()2. fetchone()3. fetchmany() 5> delete6> other step 四&#…

Spark join數據傾斜調優

Spark中常見的兩種數據傾斜現象如下 stage部分task執行特別慢 一般情況下是某個task處理的數據量遠大于其他task處理的數據量&#xff0c;當然也不排除是程序代碼沒有冗余&#xff0c;異常數據導致程序運行異常。 作業重試多次某幾個task總會失敗 常見的退出碼143、53、137…

【電路筆記】-放大器類型

放大器類型 文章目錄 放大器類型1、概述2、關于偏置的注意事項3、A類(Class A)放大器4、B類(Class B)放大器5、AB類(Class AB)放大器6、C類(Class C)放大器7、總結1、概述 放大器通常根據輸出級的結構進行分類。 事實上,功率放大確實發生在該階段,因此輸出信號的質量和…

Arduino (esp ) 下String的內存釋放

在個人的開源項目 GitHub - StarCompute/tftziku: 這是一個通過單片機在各種屏幕上顯示中文的解決方案 中為了方便快速檢索使用了string&#xff0c;于是這個string在esp8266中占了40多k,原本以為當string設置為""的時候這個40k就可以回收&#xff0c;結果發覺不行…

【JS異步編程】async/await——用同步代碼寫異步

歷史小劇場 懂得暴力的人&#xff0c;是強壯的&#xff1b;懂得克制暴力的人&#xff0c;才是強大的。----《明朝那些事兒》 什么是 async/await async: 聲明一個異步函數 自動將常規函數轉換成Promise&#xff0c;返回值也是一個Promise對象&#xff1b;只有async函數內部的異…

Java SE入門及基礎(59) 線程的實現(上) 線程的創建方式 線程內存模型 線程安全

目錄 線程&#xff08;上&#xff09; 1. 線程的創建方式 Thread類常用構造方法 Thread類常用成員方法 Thread類常用靜態方法 示例 總結 2. 線程內存模型 3.線程安全 案例 代碼實現 執行結果 線程&#xff08;上&#xff09; 1. 線程的創建方式 An application t…

利用 Docker 簡化 Nacos 部署:快速搭建 Nacos 服務

利用 Docker 簡化 Nacos 部署&#xff1a;快速搭建 Nacos 服務 引言 在微服務架構中&#xff0c;服務注冊與發現是確保服務間通信順暢的關鍵組件。Nacos&#xff08;Dynamic Naming and Configuration Service&#xff09;作為阿里巴巴開源的一個服務發現和配置管理平臺&…

任務調度器——任務切換

一、開啟任務調度器 函數原型&#xff1a; void vTaskStartScheduler( void ) 作用&#xff1a;用于啟動任務調度器&#xff0c;任務調度器啟動后&#xff0c; FreeRTOS 便會開始進行任務調度 內部實現機制&#xff08;以動態創建為例&#xff09;&#xff1a; &#xff0…

Linux 安裝、配置Tomcat 的HTTPS

Linux 安裝 、配置Tomcat的HTTPS 安裝Tomcat 這里選擇的是 tomcat 10.X ,需要Java 11及更高版本 下載頁 ->Binary Distributions ->Core->選擇 tar.gz包 下載、上傳到內網服務器 /opt 目錄tar -xzf 解壓將解壓的根目錄改名為 tomat-10 并移動到 /opt 下, 形成個人…

測評推薦:企業管理u盤的軟件有哪些?

U盤作為一種便攜的存儲設備&#xff0c;方便易用&#xff0c;被廣泛應用于企業辦公、個人學習及日常工作中。然而&#xff0c;U盤的使用也帶來了數據泄露、病毒傳播等安全隱患。為了解決這些問題&#xff0c;企業管理U盤的軟件應運而生。 本文將對市面上流行的幾款U盤管理軟件…

Hadoop3:Yarn容量調度器配置多隊列案例

一、情景描述 需求1&#xff1a; default隊列占總內存的40%&#xff0c;最大資源容量占總資源60%&#xff0c;hive隊列占總內存的60%&#xff0c;最大資源容量占總資源80%。 二、多隊列優點 &#xff08;1&#xff09;因為擔心員工不小心&#xff0c;寫遞歸死循環代碼&#…