成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C 語言變長參數及其陷阱

開發 前端
使用 C 風格的變長參數列表訪問參數并不安全。這種方法存在幾個風險,從 printInts() 函數可以看出。

C 工具

變長參數列表

這部分解釋了舊的 C 風格變長參數列表。了解這些內容很重要,因為你可能會在遺留代碼中遇到它們。然而,在新代碼中,你應該使用變參模板來實現類型安全的變長參數列表。

考慮 C 函數 printf(),來自 <cstdio>。你可以用任意數量的參數調用它:

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++ 提供了語法和一些實用宏,用于編寫你自己的變長參數函數。這些函數通常看起來很像 printf()。盡管你不經常需要這個特性,但偶爾你會遇到它相當有用的情況。例如,假設你想編寫一個快速而簡單的調試函數,當設置了調試標志時,該函數將字符串打印到 stderr,但如果沒有設置調試標志,則不執行任何操作。就像 printf() 一樣,這個函數應該能夠打印具有任意數量和任意類型參數的字符串。一個簡單的實現如下:

#include <cstdio>
#include <cstdarg>

bool debug { false };

void debugOut(const char* str, ...) {
    va_list ap;
    if (debug) {
        va_start(ap, str);
        vfprintf(stderr, str, ap);
        va_end(ap);
    }
}

首先,請注意 debugOut() 的原型包含一個類型化且命名的參數 str,后面跟著 ...(省略號)。它們代表任意數量和類型的參數。要訪問這些參數,你必須使用 <cstdarg> 中定義的宏。你聲明一個 va_list 類型的變量,并用 va_start 調用進行初始化。va_start() 的第二個參數必須是參數列表中最右邊的命名變量。所有具有變長參數列表的函數都至少需要一個命名參數。debugOut() 函數簡單地將這個列表傳遞給 vfprintf()(<cstdio> 中的標準函數)。vfprintf() 調用返回后,debugOut() 調用 va_end() 來終止訪問變量參數列表。在調用 va_start() 后,你必須始終調用 va_end(),以確保函數以一致的堆棧狀態結束。你可以如下方式使用該函數:

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);

訪問參數

如果你想自己訪問實際參數,你可以使用 va_arg() 來做到這一點。它接受 va_list 作為第一個參數,以及要解釋的參數的類型。不幸的是,除非你提供明確的方式,否則無法知道參數列表的結尾。例如,你可以使第一個參數是參數數量的計數。或者,在你有一組指針的情況下,你可能需要最后一個指針是 nullptr。有許多方法,但它們都對程序員來說是繁瑣的。

下面的示例演示了調用者在第一個命名參數中指定提供了多少個參數的技術。該函數接受任意數量的 int 并打印出來:

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;
}

你可以按以下方式調用 printInts()。請注意,第一個參數指定將跟隨多少個整數。

printInts(5, 5, 4, 3, 2, 1);

為什么不應使用 C 風格的變長參數列表

訪問風險

使用 C 風格的變長參數列表訪問參數并不安全。這種方法存在幾個風險,從 printInts() 函數可以看出:

  • 不知道參數的數量:在 printInts() 的情況下,你必須信任調用者作為第一個參數傳遞正確數量的參數。在 debugOut() 的情況下,你必須信任調用者在字符數組后傳遞的參數數量與字符數組中的格式化代碼數量相同。
  • 不知道參數的類型:va_arg() 接受一個類型,用它來解釋其當前位置的值。然而,你可以告訴 va_arg() 將值解釋為任何類型。它無法驗證正確的類型。

警告:避免使用 C 風格的變長參數列表。建議傳遞一個 std::array 或 vector 的值、使用初始化列表,或者使用類型安全的變參模板來實現變長參數列表。

責任編輯:趙寧寧 來源: coding日記
相關推薦

2022-07-03 23:07:48

Go語言參數

2022-07-04 14:41:31

Go 語言變長參數變長參數函數

2025-04-07 08:45:00

C 語言數組

2011-07-14 10:23:33

C語言

2021-07-08 23:53:44

Go語言拷貝

2022-07-28 12:17:36

C語言typedef#define

2017-07-10 08:30:11

Spark UDF變長參數

2024-09-30 11:08:18

JSON局限性數據

2023-06-26 00:03:55

Go語言類型

2010-01-11 11:27:25

C++語言

2010-01-12 17:47:31

C++語言

2010-01-11 13:31:03

C++語言

2021-02-24 15:05:32

C語言數組代碼

2011-05-13 17:25:34

C

2020-07-27 08:05:56

C++語言后端

2011-05-24 16:58:52

CC++

2022-02-28 11:13:21

數據中心自動化數據中心網絡

2021-01-06 05:29:04

C語言參數應用

2024-12-23 06:20:00

2024-03-06 13:23:56

Task.RunC#異步陷阱
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线观看国产视频 | 1区2区3区视频 | 精品成人免费一区二区在线播放 | 日日夜夜天天久久 | 在线一区 | 亚洲www啪成人一区二区麻豆 | 一级片网址| 一区在线播放 | 99精品福利视频 | 成人免费三级电影 | 91电影| 免费的一级视频 | 一区二区三区国产 | 人妖一区 | 一区二区三区国产 | 精品亚洲一区二区三区 | 亚洲国产精品99久久久久久久久 | 欧美日韩成人在线 | 男女羞羞视频在线免费观看 | 一区二区三区四区在线免费观看 | 精品日韩一区二区三区av动图 | 99精品一区二区 | 国产一级在线视频 | 欧美一区二区免费电影 | 91免费观看| 9999视频 | 干干天天 | 精品国产一区久久 | 色免费在线视频 | 午夜天堂 | 精品中文字幕一区 | 天堂视频中文在线 | 黄色毛片在线观看 | 伊人久操| 日韩www视频 | 久久久久久久久久久久91 | 日韩免费1区二区电影 | 成人欧美一区二区三区在线播放 | 亚洲国产精品一区二区www | 99视频免费 | 视频一区二区在线观看 |