柚子快報激活碼778899分享:C語言和C++中不定參數(shù)解析
柚子快報激活碼778899分享:C語言和C++中不定參數(shù)解析
你所看到的驚艷,都曾被平庸歷練
文章目錄
簡介C語言不定參數(shù)不定參宏函數(shù)
C++不定參數(shù)方法一:遞歸展開方式二:折疊表達式方法三:逗號表達式
總結(jié)
簡介
相信學(xué)過c/c++的佬們都知道,如果一個函數(shù)將自己的參數(shù)確定好后,要想使用該函數(shù)就必須傳遞合適的數(shù)量以及類型的參數(shù),然而這樣的函數(shù)非常具有局限性。例如有一個求和函數(shù),我們并不知道我們要求幾個數(shù)的和,這就導(dǎo)致在確定函數(shù)參數(shù)時無從下手,而這時候不定參數(shù)就派上了用場。
不定參數(shù)是指在函數(shù)定義時,允許接收可變數(shù)量的參數(shù)。這種機制允許函數(shù)在調(diào)用時接受不同數(shù)量的實際參數(shù),使得函數(shù)更加靈活,能夠適應(yīng)不同的使用場景。例如C語言中的printf函數(shù),scanf函數(shù)等。在C和C++中,不定參數(shù)的實現(xiàn)方式主要依賴于標準庫中的stdarg.h頭文件。
在使用不定參數(shù)后,sum函數(shù)可以接受不同數(shù)量的參數(shù),并計算它們的總和。這種靈活性使得函數(shù)能夠適應(yīng)不同的求和需求,而不需要為每種情況都定義一個單獨的函數(shù)。這樣的設(shè)計使代碼更簡潔,更容易擴展,同時提供了更大的通用性。
不定參數(shù)的優(yōu)勢:
優(yōu)勢說明靈活性不定參數(shù)函數(shù)允許在調(diào)用函數(shù)時傳遞不同數(shù)量的參數(shù),提高了函數(shù)的靈活性和通用性。適應(yīng)變化在處理不確定數(shù)量的參數(shù)或者未來可能會新增參數(shù)的情況下,不定參數(shù)函數(shù)能夠更好地適應(yīng)變化。簡化代碼使用不定參數(shù)可以簡化函數(shù)定義,避免定義多個函數(shù)處理不同數(shù)量的參數(shù)情況??勺x性在某些情況下,使用不定參數(shù)可以使函數(shù)調(diào)用更加清晰和可讀,特別是當(dāng)參數(shù)的數(shù)量可能變化時。
C語言不定參數(shù)
在C語言中,不定參數(shù)是通過stdarg.h頭文件提供的一組宏來實現(xiàn)的。這些宏主要包括va_list、va_start、va_arg和va_end。
va_list: va_list是一個類型,用于聲明一個變量,該變量將用于存儲不定參數(shù)的信息。 va_start: va_start宏用于初始化va_list,使其指向不定參數(shù)的起始位置。它接受兩個參數(shù),第一個是va_list對象,第二個是最后一個確定的參數(shù),用于確定不定參數(shù)的起始位置。 void function_with_varargs(int fixed_arg, ...) {
va_list args;
va_start(args, fixed_arg); // 現(xiàn)在args指向第一個可變參數(shù)
// ...
va_end(args);
}
va_arg: va_arg宏用于獲取當(dāng)前位置的值,并且在每次調(diào)用后,會將指針移動到下一個可變參數(shù)的位置。它接受兩個參數(shù),第一個是va_list對象,第二個是要獲取的參數(shù)的類型。 int value = va_arg(args, int);
va_end: va_end宏用于清理va_list對象,確保在使用完不定參數(shù)后正確釋放資源。 va_end(args);
如下是一個在C語言中使用不定參數(shù)的求和函數(shù):
#include
#include
int sum(int n, ...) {
va_list args; // 定義用于存儲不定參數(shù)信息的變量
va_start(args, n); // 初始化 va_list,使其指向不定參數(shù)列表的起始位置
int ret = 0;
for (int i = 0; i < n; i++) {
int tmp = va_arg(args, int); // 獲取當(dāng)前位置的參數(shù)值
ret += tmp;
}
va_end(args); // 清理 va_list,確保資源正確釋放
return ret;
}
int main() {
int ret = sum(5, 10, 24, 10, 34, 0); // 調(diào)用 sum 函數(shù),傳遞5個整數(shù)
printf("%d\n", ret); // 打印計算結(jié)果
return 0;
}
在 sum 函數(shù)中,va_start 初始化了 va_list,并使其指向傳遞給函數(shù)的不定參數(shù)的起始位置。然后,通過使用 va_arg 獲取每個參數(shù)的值,并將它們累加到 ret 變量中。最后,通過 va_end 清理 va_list,確保資源得到正確釋放。
在 main 函數(shù)中,調(diào)用了 sum 函數(shù),并將 5 個整數(shù)作為參數(shù)傳遞給它,然后打印計算結(jié)果。
不定參宏函數(shù)
除此之外,還可以在C語言中使用宏來創(chuàng)建帶有不定參數(shù)的宏函數(shù)。不定參數(shù)的宏函數(shù)通常使用__VA_ARGS__來表示可變數(shù)量的參數(shù)。
#include
#include
// 定義 LOG 宏,使用 __VA_ARGS__ 來表示可變參數(shù)
#define LOG(fmt, ...) printf("[%s : %d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
int main() {
// 使用 LOG 宏輸出日志信息,自動包含文件名和行號
LOG("登陸失敗");
return 0;
}
在這個例子中,LOG 宏使用了 __VA_ARGS__ 來表示可變參數(shù)。在調(diào)用 LOG 時,傳遞的字符串會被輸出,并自動包含文件名和行號。這樣,通過這個宏,您可以輕松地在代碼中輸出帶有文件名和行號的日志信息。
需要注意的是,在 ##__VA_ARGS__ 中的 ## 用于處理不帶參數(shù)時的情況,以防止在宏展開時產(chǎn)生語法錯誤。在可變參數(shù)為空的情況下,##__VA_ARGS__ 將會被移除,避免了末尾逗號的問題。
其中 filename.c 是當(dāng)前文件名,7 是當(dāng)前行號,登陸失敗 是通過 LOG 宏傳遞的字符串。不定參數(shù)宏函數(shù)的使用可以幫助簡化代碼,但也需要小心使用,確保在宏展開時沒有意外的副作用。
C++不定參數(shù)
C++中的不定參函數(shù)通常使用可變參數(shù)模板來實現(xiàn),這使得函數(shù)能夠接受不定數(shù)量和類型的參數(shù)。使用可變參數(shù)模板的不定參函數(shù)是 C++11 引入的特性。如果你使用的是更早版本的 C++,可能需要使用
基本模板:
template
void print(Args... args) {}
又由于無法直接獲取參數(shù)包args中的每個參數(shù),所以只能通過展開參數(shù)包的方式來獲取參數(shù)包中的每個參數(shù),這是使用可變模版參數(shù)的一個主要特點,也是最大的難點,即如何展開可變模版參數(shù)。由于語法不支持使用args[i]這樣方式獲取可變參數(shù),所以只能想一些特殊的辦法來獲取參數(shù)包的值。
方法一:遞歸展開
遞歸展開可變參數(shù)包是使用可變參數(shù)模板的一種常見技術(shù),通常用于在編譯時展開不定數(shù)量的參數(shù)。下面是一個遞歸展開可變參數(shù)包的示例:
#include
void print() {
// 終止條件,處理空參數(shù)包
}
template
void print(T first, Args... args) {
std::cout << "Cur : " << first << " args size : " << sizeof...(args) << std::endl;
print(args...); // 遞歸調(diào)用,展開參數(shù)包
}
int main() {
print("你干嘛", "哎呦", 100, 345);
return 0;
}
這個程序定義了一個函數(shù)模板 print,該函數(shù)接受任意數(shù)量和類型的參數(shù),并遞歸展開這些參數(shù)。
print 函數(shù)有兩個版本:一個是終止條件版本(空參數(shù)包時調(diào)用),另一個是遞歸版本。 在遞歸版本中,首先打印第一個參數(shù) first 和參數(shù)包的大小(使用 sizeof...(args)),然后通過 print(args...) 遞歸地調(diào)用自己,展開參數(shù)包。 在 main 函數(shù)中,你調(diào)用了 print 函數(shù),傳遞了不同類型的參數(shù)。
這樣,當(dāng)你運行程序時,print 函數(shù)將遞歸展開參數(shù)包,打印每個參數(shù)的值和參數(shù)包的大小。
這樣,通過遞歸調(diào)用,編譯器會在編譯時展開參數(shù)包,使得函數(shù)能夠處理不定數(shù)量和類型的參數(shù)。這是一種在編譯時進行模板展開的方式,相比運行時的展開更加高效。
方式二:折疊表達式
除了遞歸展開參數(shù)包的方式,C++17 引入了折疊表達式(fold expressions)的特性,這是一種更簡潔的方式來展開參數(shù)包。折疊表達式在處理可變參數(shù)包時可以提供更緊湊的語法。如下代碼:
#include
// 使用折疊表達式展開參數(shù)包
template
void print(Args... args) {
(std::cout << ... << args) << std::endl; // 折疊表達式展開參數(shù)包
}
int main() {
print("你干嘛", "哎呦", 100, 345);
return 0;
}
在這個例子中,(std::cout << ... << args) 是一個折疊表達式,用于展開參數(shù)包 args。這個表達式實際上將所有參數(shù)連接到 std::cout 流中,然后通過 << std::endl 添加換行符。
當(dāng)需要使用折疊表達式求和時,也可以如下代碼:
#include
template
int sum(Args... args) {
return (args + ...);
}
int main() {
std::cout << sum(25, 34, 59) << std::endl;
return 0;
}
代碼中使用了 C++17 中引入的折疊表達式 (args + ...) 來計算參數(shù)包中所有參數(shù)的和。在這個例子中,折疊表達式展開了 args 中的參數(shù),并使用 + 運算符對它們求和。
使用折疊表達式的好處是語法更為緊湊,而且可以在一個表達式中完成參數(shù)包的展開。這是在 C++17 及更高版本中的一種更現(xiàn)代的方式。
總體而言,遞歸展開和折疊表達式是兩種常見的方式,具體選擇取決于個人或團隊的偏好以及編譯器的支持版本。在 C++17 及更高版本中,折疊表達式通常被認為是更好的選擇。
方法三:逗號表達式
除了遞歸展開和折疊表達式,還有一種使用逗號表達式的方式展開參數(shù)包。這種方式通常結(jié)合逗號運算符 , 和初始化列表來實現(xiàn)。
以下是一個示例:
#include
// 使用逗號表達式展開參數(shù)包
template
void print(Args... args) {
int dummy[] = {(std::cout << args << " ", 0)...}; // 逗號表達式展開參數(shù)包
(void)dummy; // 防止編譯器警告未使用的變量
std::cout << std::endl;
}
int main() {
print("你干嘛", "哎呦", 100, 345);
return 0;
}
在這個例子中,逗號表達式 (std::cout << args << " ", 0) 被用于展開參數(shù)包 args。逗號表達式的返回值是初始化列表中的最后一個表達式的值(在這里是 0),而初始化列表的目的是為了創(chuàng)建一個臨時數(shù)組 dummy。
這種方式相對較獨特,通常在一些特殊情況下使用。一般而言,遞歸展開和折疊表達式更為常見和直觀,但了解這種逗號表達式的方法也是有益的。選擇展開參數(shù)包的方法通常取決于個人或團隊的偏好、代碼可讀性和編譯器支持。
總結(jié)
在C語言和C++中,可變參數(shù)是一種強大的特性,它允許函數(shù)接受可變數(shù)量和類型的參數(shù)。在C語言中,我們通常使用
C語言中的可變參數(shù):
使用
引入了可變參數(shù)模板,允許在編譯時處理可變數(shù)量和類型的參數(shù)。提高了類型安全性,無需手動管理參數(shù)的類型和數(shù)量??梢允褂眠f歸展開、折疊表達式、逗號表達式等多種方式展開可變參數(shù)包。 遞歸展開:
使用遞歸函數(shù)模板,逐一處理參數(shù)包中的每個參數(shù)。通過終止條件和遞歸調(diào)用來展開參數(shù)包。 折疊表達式:
在C++17及以后版本引入,提供了更緊湊的語法。使用(expression op ...)的形式,其中op可以是二元運算符。 逗號表達式:
使用逗號表達式展開參數(shù)包時,返回值不能直接用于數(shù)組初始化,通常使用0作為占位符??梢酝ㄟ^逗號表達式在一行中執(zhí)行多個操作。
在選擇可變參數(shù)的處理方式時,應(yīng)根據(jù)具體情況和編程需求來選擇最合適的方法。C++中的可變參數(shù)模板提供了更強大、類型安全和靈活的處理方式,但對于特定情況,C語言中的可變參數(shù)也可能是一種合適的選擇。最終,可變參數(shù)的使用應(yīng)該以代碼的清晰性、可讀性和維護性為重要考慮因素。
最后,碼文不易,如果文章對你有所幫助的話,不妨點上一個?,感謝大佬的支持!
柚子快報激活碼778899分享:C語言和C++中不定參數(shù)解析
推薦閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。