為什麼printf函式可以有任意多個引數?我們能否自己宣告乙個引數個數可變的函式?如何實現這種函式?

時間 2021-05-30 14:23:05

1樓:

CWKSC:【Just For Fun】C - 可變引數函式、可變引數巨集 __VA_ARGS__、額外的逗號

喵 (>ω<*)

但 printf() 是怎樣按照 % 去判斷需要多少個,並且從編譯期出現警告。

這個不知道。

上面那篇文章:

需要 #include 。

包括乙個型別,四個巨集函式:

型別: va_list ,用來儲存巨集va_arg()與巨集va_end()所需資訊

巨集函式:va_start(), va_arg(), va_end(), va_copy()

va_list

va_start()

va_arg()

va_end()

va_copy()

除了 va_copy() 是 C99 外,其餘都是相容於 C89 。

intsum

(int

num,

...)

va_end

(args

);return

sum;

}先宣告乙個 va_list 型別的變數,

va_start() 有兩個引數:

第乙個是 va_list 型別的變數,

第二個是可變引數 ... 的前乙個的變數名,這裡是 num 。

va_arg() 用於獲得額外引數的數值,同樣有兩個引數:

第乙個也是 va_list 型別的變數,

第二個是載入的引數型別。

注意載入的引數型別不可為:

char、signed char、unsigned char

short、unsigned short

signed short、short int、signed short int、unsigned short int

float

會有預設引數提公升(default argument promotions)

float型別的實際引數將提公升到double

char、short和相應的signed、unsigned型別的實際引數提公升到int

如果int不能儲存原值,則提公升到unsigned int

可參看 C語言可變長引數函式與預設引數提公升

最後使用 va_end() ,像 fclose() 一樣把可變引數關掉。

乙個引數,va_list 型別的變數。

可變引數函式的詳細實現及原理可參看 可變引數函式詳解 - clover_toeic - 部落格園

和知乎上其他人的另一篇文章 C語言中可變引數函式實現原理

由 C99 引入,

宣告語法類似於可變引數函式:逗號後面三個句點"...",表示乙個或多個引數。

但常見編譯器也允許傳遞0個引數。

巨集擴充套件時使用特殊識別符號__VA_ARGS__表示所傳遞的引數的替換。

沒辦法訪問可變引數列表內的單個引數,也不能獲知多少個引數被傳遞。

例子:#define foo(f, ...) printf(f, __VA_ARGS__)

foo("%d%d", x, y); 等價 printf("%d%d", x, y);

接收了兩個額外引數。

注意沒辦法訪問可變引數列表內的單個引數,也不能獲知多少個引數被傳遞。

所以不能夠像可變引數函式一樣,

以「簡單直觀」的方法去實現可變引數的 sum()。

若果額外引數的數目為 0 ,即 foo("123"); ,

會被展開為 printf("123",) ,這裡出現了乙個額外的逗號。

可把 __VA_ARGS__ 改為 ##__VA_ARGS__ ,

去提示編譯器,會自動把逗號去除。

我記得這是編譯器擴充套件。如果不想用編譯器擴充套件,可以看看:

c - Standard alternative to GCC's ##__VA_ARGS__ trick? - Stack Overflow

下面有乙個喪心病狂的答案。

Visual C++ 貌似不用提醒也會自動去除。

Visual Studio 貌似限定了不能直接使用,(我不確定)

需要在第二次展開巨集時才會生效,所以我了封裝乙個:

#define eatCommaVA_ARGS__

來給 VS 用。

Python 裡為什麼函式可以返回乙個函式內部定義的函式?

鋼鐵直男劉昊然 自界說函式的呼叫是經過訪問自界說函式名來完成的,變數 函式名 參量1,參量2,明顯,與呼叫子程式的辦法不同,自界說函式的呼叫遵從內部函式 如Sin Sqr Tan等 的呼叫規矩,自帶參量也有必要用圓括號括起來。參量可所以常量 變數 表示式或陣列變數名。資料的型別應與子程式界說時的參量...

為什麼優化損失函式的上界可以優化損失函式?

DomainAdaptation 題主所說的應該是非凸的0 1損失函式和相應的替代損失函式吧。在非代價敏感的分類的問題中,我們最容易想到就是用0 1損失函式來度量錯分樣本的損失。但由於0 1損失非凸,不好優化,於是人們採用了一系列的替代損失函式 surragate loss function 來替代...

為什麼冪函式不叫底數函式

令狐帝主 冪函式叫底數函式完全沒問題,而且跟指數函式對應,底數函式 指數函式描述了自變數的位置。而對數函式,可以認為求自變數 真數 之對數的函式。 趙洪生 能找到這裡的人,說明都經歷了思考,我也是一樣的。可以心裡把它叫為底數函式,說出來的時候還是冪函式,自己明白的同時也能跟別人交流。話說另外的問題,...