新聞中心
C 工具
變長(zhǎng)參數(shù)列表
這部分解釋了舊的 C 風(fēng)格變長(zhǎng)參數(shù)列表。了解這些內(nèi)容很重要,因?yàn)槟憧赡軙?huì)在遺留代碼中遇到它們。然而,在新代碼中,你應(yīng)該使用變參模板來(lái)實(shí)現(xiàn)類型安全的變長(zhǎng)參數(shù)列表。

十年的君山網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷型網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整君山建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“君山網(wǎng)站設(shè)計(jì)”,“君山網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
考慮 C 函數(shù) printf(),來(lái)自
printf("int %d\n", 5);
printf("String %s and int %d\n", "hello", 5);
printf("Many ints: %d, %d, %d, %d, %d\n", 1, 2, 3, 4, 5);C/C++ 提供了語(yǔ)法和一些實(shí)用宏,用于編寫(xiě)你自己的變長(zhǎng)參數(shù)函數(shù)。這些函數(shù)通??雌饋?lái)很像 printf()。盡管你不經(jīng)常需要這個(gè)特性,但偶爾你會(huì)遇到它相當(dāng)有用的情況。例如,假設(shè)你想編寫(xiě)一個(gè)快速而簡(jiǎn)單的調(diào)試函數(shù),當(dāng)設(shè)置了調(diào)試標(biāo)志時(shí),該函數(shù)將字符串打印到 stderr,但如果沒(méi)有設(shè)置調(diào)試標(biāo)志,則不執(zhí)行任何操作。就像 printf() 一樣,這個(gè)函數(shù)應(yīng)該能夠打印具有任意數(shù)量和任意類型參數(shù)的字符串。一個(gè)簡(jiǎn)單的實(shí)現(xiàn)如下:
#include
#include
bool debug { false };
void debugOut(const char* str, ...) {
va_list ap;
if (debug) {
va_start(ap, str);
vfprintf(stderr, str, ap);
va_end(ap);
}
} 首先,請(qǐng)注意 debugOut() 的原型包含一個(gè)類型化且命名的參數(shù) str,后面跟著 ...(省略號(hào))。它們代表任意數(shù)量和類型的參數(shù)。要訪問(wèn)這些參數(shù),你必須使用
debug = true;
debugOut("int %d\n", 5);
debugOut("String %s and int %d\n", "hello", 5);
debugOut("Many ints: %d, %d, %d, %d, %d\n", 1, 2, 3, 4, 5);訪問(wèn)參數(shù)
如果你想自己訪問(wèn)實(shí)際參數(shù),你可以使用 va_arg() 來(lái)做到這一點(diǎn)。它接受 va_list 作為第一個(gè)參數(shù),以及要解釋的參數(shù)的類型。不幸的是,除非你提供明確的方式,否則無(wú)法知道參數(shù)列表的結(jié)尾。例如,你可以使第一個(gè)參數(shù)是參數(shù)數(shù)量的計(jì)數(shù)?;蛘撸谀阌幸唤M指針的情況下,你可能需要最后一個(gè)指針是 nullptr。有許多方法,但它們都對(duì)程序員來(lái)說(shuō)是繁瑣的。
下面的示例演示了調(diào)用者在第一個(gè)命名參數(shù)中指定提供了多少個(gè)參數(shù)的技術(shù)。該函數(shù)接受任意數(shù)量的 int 并打印出來(lái):
void printInts(size_t num, ...) {
va_list ap;
va_start(ap, num);
for (size_t i { 0 }; i < num; ++i) {
int temp { va_arg(ap, int) };
cout << temp << " ";
}
va_end(ap);
cout << endl;
}你可以按以下方式調(diào)用 printInts()。請(qǐng)注意,第一個(gè)參數(shù)指定將跟隨多少個(gè)整數(shù)。
printInts(5, 5, 4, 3, 2, 1);為什么不應(yīng)使用 C 風(fēng)格的變長(zhǎng)參數(shù)列表
訪問(wèn)風(fēng)險(xiǎn)
使用 C 風(fēng)格的變長(zhǎng)參數(shù)列表訪問(wèn)參數(shù)并不安全。這種方法存在幾個(gè)風(fēng)險(xiǎn),從 printInts() 函數(shù)可以看出:
- 不知道參數(shù)的數(shù)量:在 printInts() 的情況下,你必須信任調(diào)用者作為第一個(gè)參數(shù)傳遞正確數(shù)量的參數(shù)。在 debugOut() 的情況下,你必須信任調(diào)用者在字符數(shù)組后傳遞的參數(shù)數(shù)量與字符數(shù)組中的格式化代碼數(shù)量相同。
- 不知道參數(shù)的類型:va_arg() 接受一個(gè)類型,用它來(lái)解釋其當(dāng)前位置的值。然而,你可以告訴 va_arg() 將值解釋為任何類型。它無(wú)法驗(yàn)證正確的類型。
警告:避免使用 C 風(fēng)格的變長(zhǎng)參數(shù)列表。建議傳遞一個(gè) std::array 或 vector 的值、使用初始化列表,或者使用類型安全的變參模板來(lái)實(shí)現(xiàn)變長(zhǎng)參數(shù)列表。
當(dāng)前標(biāo)題:C 語(yǔ)言變長(zhǎng)參數(shù)及其陷阱
網(wǎng)頁(yè)路徑:http://m.fisionsoft.com.cn/article/cciogjc.html


咨詢
建站咨詢
