C語言深入淺出可變引數函式的使用技巧

2021-05-27 17:33:06 字數 2606 閱讀 1747

va函式(variable argument function),引數個數可變函式,又稱可變引數函式。c/c++程式設計中,系統提供給程式設計人員的va函式很少。*printf()/*scanf()系列函式,用於輸入輸出時格式化字串;exec*()系列函式,用於在程式中執行外部檔案(main(int argc,char*argv算不算呢,與其說main()也是乙個可變引數函式,倒不如說它是exec*()經過封裝後的具備特殊功能和意義的函式,至少在原理這一級上有很多相似之處)。由於引數個數的不確定,使va函式具有很大的靈活性,易用性,對沒有使用過可變引數函式的程式設計人員很有**力;那麼,該如何編寫自己的va函式,va函式的運用時機、編譯實現又是如何。作者借本文談談自己關於va函式的一些淺見。

一、 從printf()開始

從大家都很熟悉的格式化字串函式開始介紹可變引數函式。

原型:int printf(const char * format, ...);

引數format表示如何來格式字串的指令,…

表示可選引數,呼叫時傳遞給"..."的引數可有可無,根據實際情況而定。

系統提供了vprintf系列格式化字串的函式,用於程式設計人員封裝自己的i/o函式。

int vprintf / vscanf(const char * format, va_list ap); // 從標準輸入/輸出格式化字串

int vfprintf / vfsacanf(file * stream, const char * format, va_list ap);// 從檔案流

int vsprintf / vsscanf(char * s, const char * format, va_list ap); // 從字串

// 例1:格式化到乙個檔案流,可用於日誌檔案

file *logfile;

int writelog(const char * format, ...)

…// 呼叫時,與使用printf()沒有區別。

writelog("%04d-%02d-%02d %02d:%02d:%02d  %s/%04d logged out.", nyear, nmonth, nday, nhour, nminute, szusername, nuserid);

同理,也可以從檔案中執行格式化輸入;或者對標準輸入輸出,字串執行格式化。

在上面的例1中,writelog()函式可以接受引數個數可變的輸入,本質上,它的實現需要vprintf()的支援。如何真正實現屬於自己的可變引數函式,包括控制每乙個傳入的可選引數。

二、 va函式的定義和va巨集

c語言支援va函式,作為c語言的擴充套件--c++同樣支援va函式,但在c++中並不推薦使用,c++引入的多型性同樣可以實現引數個數可變的函式。不過,c++的過載功能畢竟只能是有限多個可以預見的引數個數。比較而言,c中的va函式則可以定義無窮多個相當於c++的過載函式,這方面c++是無能為力的。va函式的優勢表現在使用的方便性和易用性上,可以使**更簡潔。c編譯器為了統一在不同的硬體架構、硬體平台上的實現,和增加**的可移植性,提供了一系列巨集來遮蔽硬體環境不同帶來的差異。

ansi c標準下,va的巨集定義在stdarg.h中,它們有:va_list,va_start(),va_arg(),va_end()。

// 例2:求任意個自然數的平方和:

int sqsum(int n1, ...)

va_end(arg_ptr);

return nsqsum;

}// 呼叫時

int nsqsum = sqsum(7, 2, 7, 11, -1);

可變引數函式的原型宣告格式為:

type vafunction(type arg1, type arg2, … );

引數可以分為兩部分:個數確定的固定引數和個數可變的可選引數。函式至少需要乙個固定引數,固定引數的宣告和普通函式一樣;可選引數由於個數不確定,宣告時用"…"表示。固定引數和可選引數公同構成乙個函式的引數列表。借助上面這個簡單的例2,來看看各個va_***的作用。

va_list arg_ptr:定義乙個指向個數可變的引數列表指標;va_start(arg_ptr, argn):使引數列表指標arg_ptr指向函式引數列表中的第乙個可選引數,說明:argn是位於第乙個可選引數之前的固定引數,(或者說,最後乙個固定引數;…之前的乙個引數),函式引數列表中引數在記憶體中的順序與函式宣告時的順序是一致的。如果有一va函式的宣告是void va_test(char a, char b, char c, …),則它的固定引數依次是a,b,c,最後乙個固定引數argn為c,因此就是va_start(arg_ptr, c)。

va_arg(arg_ptr, type):返回引數列表中指標arg_ptr所指的引數,返回型別為type,並使指標arg_ptr指向引數列表中下乙個引數。

va_copy(dest, src):dest,src的型別都是va_list,va_copy()用於複製引數列表指標,將dest初始化為src。

va_end(arg_ptr):清空引數列表,並置引數指標arg_ptr無效。說明:指標arg_ptr被置無效後,可以通過呼叫va_start()、va_copy()恢復arg_ptr。每次呼叫va_start() / va_copy()後,必須得有相應的va_end()與之匹配。引數指標可以在引數列表中隨意地來回移動,但必須在va_start() … va_end()之內。

轉貼:

C語言深入淺出可變引數函式的使用技巧

注意 可變引數函式只有在引數是ansi的情況下才有用,即使引數是引用也不行。深入淺出可變引數函式的使用技巧本文主要介紹可變引數的函式使用,然後分析它的原理,程式設計師自己如何對它們實 現和封裝,最後是可能會出現的問題和避免措施。va函式 variable argument function 引數個數...

深入淺出可變引數函式的使用技巧

本文主要介紹可變引數的函式使用,然後分析它的原理,程式設計師自己如何對它們實 現和封裝,最後是可能會出現的問題和避免措施。va函式 variable argument function 引數個數可變函式,又稱可變引數函式 c c 程式設計中,系統提供給程式設計人員的va函式很少。printf sca...

深入淺出學Hive Hive引數

第一部分 hive 引數 hive.exec.max.created.files 說明 所有hive執行的map與reduce任務可以產生的檔案的和 預設值 100000 hive.exec.dynamic.partition 說明 是否為自動分割槽 預設值 false hive.mapred.re...