首頁 > 軟體

C語言中不定引數 ... 的語法以及函數封裝

2023-01-28 18:03:10

Intro

有一天看C程式碼看到某個方法有這樣的定義:在函數形參列表處,有...的寫法,就像Java中的不定引數那樣。
如:

int	 printf(const char * __restrict, ...) __printflike(1, 2);
int	 scanf(const char * __restrict, ...) __scanflike(1, 2);

那麼C語言中的不定引數特性,是怎樣使用的呢,以及我們如何利用該特性,封裝自己的函數?

語法測試

依賴庫

需要用到 stdarg.h 中的三個函數:

#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_end(ap)          __builtin_va_end(ap)
#define va_arg(ap, type)    __builtin_va_arg(ap, type)

新函數使用測試:遍歷並列印不定引數中的值

主要是測試一下上面提到的三個庫函數的使用。

#include <stdio.h>
#include <stdarg.h>

// 宣告列表的結束值
#define ARGUMENTS_END_VALUE -1

void printMultiArgs(int firstArgs, ...) {

    // 宣告參數列的變數
    va_list ap;
    
    // 初始化參數列
    va_start(ap, firstArgs);
    printf("%dn", firstArgs);
    
    int currValue;
    while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) {
        printf("%dn", currValue);
    }

    // 結束參數列
    va_end(ap);
}

int main(int argc, const char * argv[]) {
    printMultiArgs(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE);
    return 0;
}

用兩種方式封裝函數:對多個int值求和

//
//  main.c
//  C不定引數
//
//  Created by wuyujin1997 on 2023/1/23.
//

//#define va_start(ap, param) __builtin_va_start(ap, param)
//#define va_end(ap)          __builtin_va_end(ap)
//#define va_arg(ap, type)    __builtin_va_arg(ap, type)

#include <stdio.h>
#include <stdarg.h>

// 宣告列表的結束值
#define ARGUMENTS_END_VALUE -1

void printMultiArgs(int firstArgs, ...) {

    // 宣告參數列的變數
    va_list ap;
    // 初始化參數列
    va_start(ap, firstArgs);
    printf("%dn", firstArgs);
    
    int currValue;
    while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) {
        printf("%dn", currValue);
    }

    // 結束參數列
    va_end(ap);
}


/// 對多個int變數求和(需要提前約定好引數結束的標誌值 ARGUMENTS_END_VALUE)
/// - Parameter firstArgs: <#firstArgs description#>
int sum1(int firstArgs, ...) {
    int result = 0;
    
    va_list ap;
    va_start(ap, firstArgs);
    result+= firstArgs; // 手動處理第一個引數
    int currValue;
    while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) {
        result += currValue;
    }
    va_end(ap);
    
    return result;
}


/// 對多個int變數求和(需要主動本方法:不定引數的個數是多少)
/// - Parameters:
///   - count: 不定引數的個數
///   - firstArgs: 第一個引數,顯式的形參
int sum2(int count, int firstArgs, ...) {
    int result = 0;
    
    va_list ap;
    va_start(ap, firstArgs);
    result += firstArgs;
    for (int i = 1; i < count; i++) {
        int currValue = va_arg(ap, int);
//        printf("%d  %dn", i, currValue);
        result += currValue;
    }
    va_end(ap);
    
    return result;
}

int main(int argc, const char * argv[]) {

    printMultiArgs(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE);
    printf("sum1  %dn", sum1(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE));
    int LENGTH = 9;
    printf("sum2  %dn", sum2(LENGTH, 1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE));

    return 0;
}

執行結果:

總結

  • 需要引入標頭檔案 #include <stdarg.h>
  • 一個新型別,三個新函數
    • 型別 va_list
    • 函數,其中 ap 為 va_list 型別的變數。
      • va_start(ap, param) param為不定參數列的第一個引數。
      • va_arg(ap, type) 不定引數中變數的型別嗎,如int, short, long 等。
      • va_end(ap)
  • 如何確定 va_arg 的size/有多少個元素? 沒有原生的屬性/變數可以告訴我們。
    • 約定一個值作為 end_value ,而且要保證:這個值不會出現在傳入的多個引數值中。
    • 在咱自己封裝的函數中,新增一個引數用於告知被調函數內部:本次不定引數的size是多少。
  • 注意不定引數的型別匹配。

總結 

到此這篇關於C語言中不定引數 ... 的語法以及函數封裝的文章就介紹到這了,更多相關C語言不定引數 ...內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com