① c語言 怎麼寫 可變 參數函數
#include<stdarg.h>//可變參數函數必要的頭文件
#include<stdio.h>
longintsum(unsignedintargc,...)//可變參數函數必須包含至少一個確定的參數
{
longintsrt=0;
intva;
unsignedinti;
va_listvl;//用於指向可變參數列表
va_start(vl,argc);//初始化,va_start()調用的第一個參數是所編寫的可變參數函數的最後一個確定的參數
for(i=0;i<argc;i++){
srt+=(int)va_arg(vl,int);//從參數列表按提取一個int類型的值參與相加運算
}
va_end(vl);//清理
returnsrt;
}
intmain(intargc,char*argv[])
{
printf("%ld ",sum(3,1,2,3));
return0;
}
② C語言中如何獲取函數可變參數的個數
這個看你是怎麼調用的
一般都是約定個數 或者根據第一個參數,決定個數。
你這個寫法,看起來是兩個參數調用,然後都是char* 如果是這樣
要改成
#include<stdio.h>
#include<stdarg.h>
voidprint(char*value,...)
{
char*t;
printf(value);
va_listval;
va_start(val,value);
t=va_arg(val,char*);//獲取下一個參數需要賦值的。
printf(t);
va_end(val);
}
③ 如何在C語言中實現可變長度的參數
C語言實現可變長度字元串,主要依靠realloc函數實現,主要代碼如下,
//程序功能,判斷插入字元長度len,若大於預設大小n,調整字元串數組大小,實現動態處理數組大小。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char * pstr = NULL;
int n=10;//字元串初始大小
char str[100];//待插入字元串
int len=0;//待插入字元串長度
pstr = (char*)malloc(sizeof(char)*n);//申請sizeof(char)*n個大小的內存空間
if (pstr==NULL)
{
printf("內存申請出錯,程序退出!\n");
exit(1);
}
④ c語言如何封裝一個帶有可變參數的方法
需要借用C語言的VA_LIST宏定義,及相關操作來實現可變參數。
VA_LIST所在頭文件:#include <stdarg.h>,用法如下:
(1)首先在函數里定義一具VA_LIST型的變數,這個變數是指向參數的指針;
(2)然後用VA_START宏初始化剛定義的VA_LIST變數;
(3)然後用VA_ARG返回可變的參數,VA_ARG的第二個參數是你要返回的參數的類型(如果函數有多個可變參數的,依次調用VA_ARG獲取各個參數);
(4)最後用VA_END宏結束可變參數的獲取。
以下是一個自定義列印介面的實現:
intmy_printf(constchar*fmt,...)//...表示參數可變
{
va_listargs;//定義va_list
staticchargc_PrintfOutBuff[1000];
va_start(args,fmt);//初始化
vsnprintf((char*)gc_PrintfOutBuff,1000,(char*)fmt,args);//這里沒有使用VA_ARG取回單個變數,而是借用vsnprinf一次性讀取。
va_end(args);//結束獲取
puts("%s",(constchar*)gc_PrintfOutBuff);//使用。
return0;
}
⑤ C++ 多個函數參數問題
可變參數即表示參數個數可以變化,可多可少,也表示參數的類型也可以變化,可以是int,double還可以是char*,類,結構體等等。可變參數是實現printf(),sprintf()等函數的關鍵之處,也可以用可變參數來對任意數量的數據進行求和,求平均值帶來方便(不然就用數組或每種寫個重載)。在C#中有專門的關鍵字parame,但在C,C++並沒有類似的語法,不過幸好提供這方面的處理函數,本文將重點介紹如何使用這些函數。
第一步 可變參數表示
用三個點…來表示,查看printf()函數和scanf()函數的聲明:
int printf(const char *, ...);
int scanf(const char *, ...);
這三個點用在宏中就是變參宏(Variadic Macros),默認名稱為__VA_ARGS__。如:
#define WriteLine(...) { printf(__VA_ARGS__); putchar('\n');}
再WriteLine("MoreWindows");
考慮下printf()的返回值是表示輸出的位元組數。將上面宏改成:
#define WriteLine (...) printf(__VA_ARGS__) + (putchar('\n') != EOF ? 1: 0);
這樣就可以得到WriteLine宏的返回值了,它將返回輸出的位元組數,包括最後的』\n』。如下例所示i和j都將輸出12。
int i = WriteLine("MoreWindows");
WriteLine("%d", i);
int j = printf("%s\n", "MoreWindows");
WriteLine("%d", j);
第二步 如何處理va_list類型
函數內部對可變參數都用va_list及與它相關的三個宏來處理,這是實現變參參數的關鍵之處。
在<stdarg.h>中可以找到va_list的定義:
typedef char * va_list;
再介紹與它關系密切的三個宏要介紹下:va_start(),va_end()和va_arg()。
同樣在<stdarg.h>中可以找到這三個宏的定義:
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_end(ap) ( ap = (va_list)0 )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
其中用到的_INTSIZEOF宏定義如下:
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
來分析這四個宏:
va_end(ap)這個最簡單,就是將指針置成NULL。
va_start(ap,v)中ap = (va_list)&v + _INTSIZEOF(v)先是取v的地址,再加上_INTSIZEOF(v)。_INTSIZEOF(v)就有點小復雜了。( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )全是位操作,看起來有點麻煩,其實不然,非常簡單的,就是取整到sizeof(int)。比如sizeof(int)為4,1,2,3,4就取4,5,6,7,8就取8。對x向n取整用C語言的算術表達就是((x+n-1)/n)*n,當n為2的冪時可以將最後二步運算換成位操作——將最低 n - 1個二進制位清 0就可以了。
va_arg(ap,t)就是從ap中取出類型為t的數據,並將指針相應後移。如va_arg(ap, int)就表示取出一個int數據並將指針向移四個位元組。
因此在函數中先用va_start()得到變參的起始地址,再用va_arg()一個一個取值,最後再用va_end()收尾就可以解析可變參數了。
第三步 vfprintf()函數和vsprintf()函數
vfprintf()這個函數很重要,光從名字上看就知道它與經常使用的printf()函數有很大的關聯。它有多個重載版本,這里講解最常用的一種:
函數原型
int vfprintf(
FILE *stream,
const char *format,
va_list argptr
);
第一個參數為一個FILE指針。FILE結構在C語言的讀寫文件必不可少。要對屏幕輸出傳入stdout。
第二個參數指定輸出的格式。
第三個參數是va_list類型,這個少見,但其實就是一個char*表示可變參參數的起始地址。
返回值:成功返回輸出的位元組數(不包括最後的』\0』),失敗返回-1。
vsprintf()與上面函數類似,就只列出函數原型了:
int vsprintf(
char *buffer,
const char *format,
va_list argptr
);
還有一個int _vscprintf(const char *format, va_list argptr );可以用來計算vsprintf()函數中的buffer字元串要多少位元組的空間。
代碼範例
下面就給出了自己實現的printf()函數(注1)與WriteLine()函數
int Printf(char *pszFormat, ...)
{
va_list pArgList;
va_start(pArgList, pszFormat);
int nByteWrite = vfprintf(stdout, pszFormat, pArgList);
va_end(pArgList);
return nByteWrite;
}
int WriteLine(char *pszFormat, ...)
{
va_list pArgList;
va_start(pArgList, pszFormat);
int nByteWrite = vfprintf(stdout, pszFormat, pArgList);
if (nByteWrite != -1)
putchar('\n'); //注2
va_end(pArgList);
return (nByteWrite == -1 ? -1 : nByteWrite + 1);
}
調用與printf()函數相同。
再給出一個用可變參數來求和,遺憾的在C,C++中無法確定傳入的可變參數的個數(printf()中是通過掃描'%'個數來確實參數的個數的),因此要麼就要指定個數,要麼在參數的最後要設置哨兵數值:
設置哨兵數值:
const int GUARDNUMBER = 0; //哨兵標識
//變參參數的個數無法確定,在printf()中是通過掃描'%'個數,在這通過設置哨兵標識來確定變參參數的終止
int MySum(int i, ...)
{
int sum = i;
va_list argptr;
va_start(argptr, i);
while ((i = va_arg(argptr, int)) != GUARDNUMBER)
sum += i;
va_end(argptr);
return sum;
}
可以這樣的調用: printf("%d\n", MySum(1, 3, 5, 7, 9, 0));
但不可以直接傳入一個0: printf("%d\n", MySum(0)); //error
指定個數:
int MySum(int nCount, ...)
{
if (nCount <= 0)
return 0;
int sum = 0;
va_list argptr;
va_start(argptr, nCount);
for (int i = 0; i < nCount; i++)
sum += va_arg(argptr, int);
va_end(argptr);
return sum;
}
調用時第一個參數表示後面參數的個數如:
printf("%d\n", MySum(5, 1, 3, 5, 7, 9));
printf("%d\n", MySum(0));
代碼所用的頭文件:
#include <stdarg.h>
#include <stdio.h>
可變參數的使用方法遠遠不止上述幾種,不過在C,C++中使用可變參數時要小心,在使用printf()等函數時傳入的參數個數一定不能比前面的格式化字元串中的』%』符號個數少,否則會產生訪問越界,運氣不好的話還會導致程序崩潰。
⑥ c語言中什麼是參數
如何寫可變參數的C函數以及這些可變參數的函數編譯器是如何實現的呢?下面是我為大家整理的關於c語言的參數介紹及使用,希望可以幫到大家哦。
簡單的可變參數的C函數
下面我們來探討如何寫一個簡單的可變參數的C函數.寫可變參數的C函數要在程序中用到以下這些宏:
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );
va在這里是variable-argument(可變參數)的意思.
這些宏定義在stdarg.h中,所以用到可變參數的程序應該包含這個頭文件.下面我們寫一個簡單的可變參數的函數,改函數至少有一個整數參數,第二個參數也是整數,是可選的.函數只是列印這兩個參數的值.
void simple_va_fun(int i, ...)
{
va_list arg_ptr;
int j=0;
va_start(arg_ptr, i);
j=va_arg(arg_ptr, int);
va_end(arg_ptr);
printf(%d %dn, i, j);
return;
}
我們可以在我們的頭文件中這樣聲明我們的函數:
extern void simple_va_fun(int i, ...);
我們在程序中可以這樣調用:
simple_va_fun(100);
simple_va_fun(100,200);
從這個函數的實現可以看到,我們使用可變參數應該有以下步驟:
1)首先在函數里定義一個va_list型的變數,這里是arg_ptr,這個變數是指向參數的指針.
2)然後用va_start宏初始化變數arg_ptr,這個宏的第二個參數是第一個可變參數的前一個參數,是一個固定的參數.
3)然後用va_arg返回可變的參數,並賦值給整數j. va_arg的第二個參數是你要返回的參數的類型,這里是int型.
4)最後用va_end宏結束可變參數的獲取.然後你就可以在函數里使用第二個參數了.如果函數有多個可變參數的,依次調用va_arg獲取各個參數.
如果我們用下面三種 方法 調用的話,都是合法的,但結果卻不一樣:
1)simple_va_fun(100);
結果是:100 -123456789(會變的值)
2)simple_va_fun(100,200);
結果是:100 200
3)simple_va_fun(100,200,300);
結果是:100 200
我們看到第一種調用有錯誤,第二種調用正確,第三種調用盡管結果正確,但和我們函數最初的設計有沖突.下面一節我們探討出現這些結果的原因和可變參數在編譯器中是如何處理的.
可變參數在編譯器中的處理我們知道va_start,va_arg,va_end是在stdarg.h中被定義成宏的,由於1)硬體平台的不同 2)編譯器的不同,所以定義的宏也有所不同,下
面以VC++中stdarg.h里x86平台的宏定義摘錄如下(''號表示折行):
typedef char * va_list;
#define _INTSIZEOF(n)
((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)
( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
⑦ 如何在C語言中定義參數數目可變的函數
定義如下:
<函數返回值> 函數名(形參1, 形參2, ...)
舉例說明:
intfunc(inta,intb,...)
{
//函數體
......
}
printf()函數就是一個參數可變的函數,其函數原型為:
intprintf(constchar*__format,...);