函數不定參數個數的實現


1. C語言函數的調用方式 _cdecl 調用

_cdecl 是C Declaration的縮寫(declaration,聲明),表示C語言默認的函數調用方法:所有參數從右到左依次入棧,這些參數由調用者清除,稱為手動清棧所以在函數調用棧中, 越右邊的參數在棧的越低端,既內存地址越大。

2.實現

函數如何實現不定參數:由於在C語言中沒有函數重載,解決不定數目函數參數問題變得比較麻煩,即使采用C++,如果參數個數不能確定,也很難采用函數重載。對這種情況,提出了指針參數來解決問題。

(1)va_list

  定義了一個指針arg_ptr, 用於指示可選的參數.

(2)va_start(arg_ptr, argN)

  使參數列表指針arg_ptr指向函數參數列表中的第一個可選參數,argN是位於第一個可選參數之前的固定參數,

  或者說最后一個固定參數.如有一va 函數的聲明是void va_test(char a, char b, char c, ...), 則它的固定參數依次是a,b,c, 最后一個固定參數argN為c, 因此就是va_start (arg_ptr, c).

(3)va_arg(arg_ptr, type)

  返回參數列表中指針arg_ptr所指的參數, 返回類型為type. 並使指針arg_ptr指向參數列表中下一個參數.返回的是可選參數, 不包括固定參數.

(4)va_end(arg_ptr)

  清空參數列表, 並置參數指針arg_ptr無效.

  (注:va在這里是variable-argument(可變參數)的意思.   這些宏定義在stdarg.h中,所以用到可變參數的程序應該包含這個頭文件)

過程:

調用va_start()后parg將指向第一個不固定的參數,在這個函數中也就是v2后面的參數。

接着調用va_parg():va_parg同樣接受兩個參數第一個參數是經過va_start()處理過后的parg指針。

第二個參數是期望不固定參數的類型,編譯器無法確定可變參數的類型,但是必須這么做。

va_parg返回parg當前指向的那個可變的參數。並且每次調用都會更新這個指針,使得parg向下個參數移動;

最后調用va_end():va_end接受一個參數,parg,他會將parg重置為NULL;沒用調用va_end函數將無法運行。

3.舉例

(1)固定參數個數(2個)

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

int print(const char *format, ...)
{
    va_list args;
    const char *args1;
    va_start(args, format);
    args1 = va_arg(args,const char *);
    va_end(args);
    printf("format=%s args1=%s", format, args1);
}
int main()
{
    print("11111", "22222");
}

運行結果:

format=11111 args1=22222

(2)多個參數(采用循環)

double average(double v1, double v2, ...){
    va_list parg;
    //將parg指向第一個不固定的參數
    va_start(parg, v2);
    double sum = 0.0;
    sum = v1 + v2;
    double value;
    int count = 2;
    //va_arg判斷下一個不固定參數類型是否為double
    while((value = va_arg(parg, double)) != 0.0){
        sum += value;
        ++count;
    }
    va_end(parg);
    return sum/count;
 
}


4.注意

va_arg(ap,type)中的type絕對不能為以下類型:
——char、signed char、unsigned char
——short、unsigned short
——signed short、short int、signed short int、unsigned short int
——float

 

參考:

https://www.cnblogs.com/linhaostudy/p/6695422.html

https://blog.csdn.net/wabil/article/details/72800624?utm_source=blogxgwz0

https://blog.csdn.net/bristar_zon/article/details/48465021

https://blog.csdn.net/qq_25367755/article/details/50946574


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM