當前位置:首頁 » 編程語言 » C語言如何定義變參函數
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

C語言如何定義變參函數

發布時間: 2022-09-23 23:08:14

㈠ 在c語言中形參與實參是如何定義的

在C語言中,形參即為形式參數。它在整個函數編譯的時候,沒有實際的數據賦於它,僅僅作於定義某個函數或者函數名。
而實參既為實際參數。顧名思義,在函數中,有一個特定的數據賦值給它,可以作於在函數中進行運算。
比如:
void main()
{
int a=1,b;
b=function(a); //a作於在函數中進行運算,是實參
}
int function(int c) //c作於定義function函數,是形參
{}

㈡ c語言中的sprintf函數

1.
sprintf
是個變參函數,定義如下:
int
sprintf(
char
*buffer,
const
char
*format
[,
argument]
...
);
除了前兩個參數類型固定外,後面可以接任意多個參數。而它的精華,顯然就在第二個參數:格式化字元串上。
2.
sprintf
使用格式化字元串來指定串的格式,在格式串內部使用一些以「%」開頭的格式說明符(format
specifications)來占據一個位置,在後邊的變參列表中提供相應的變數,最終函數就會用相應位置的變數來替代那個說明符,產生一個調用者想要的字元串。
3.
sprintf
最常見的應用之一莫過於把整數列印到字元串中,所以,spritnf
在大多數場合可以替代itoa。

㈢ 如何在C語言中定義參數數目可變的函數

定義如下:

<函數返回值> 函數名(形參1, 形參2, ...)

舉例說明:

intfunc(inta,intb,...)
{
//函數體
......
}

printf()函數就是一個參數可變的函數,其函數原型為:

intprintf(constchar*__format,...);

㈣ C語言變參函數Printf實現機制是什麼

在C/C++中,對函數參數的掃描是從後向前的。C/C++的函數參數是通過壓入堆棧的方式來給函數傳參數的(堆棧是一種先進後出的數據結構),最先壓入的參數最後出來,在計算機的內存中,數據有2塊,一塊是堆,一塊是棧(函數參數及局部變數在這里),而棧是從內存的高地址向低地址生長的,控制生長的就是堆棧指針了,最先壓入的參數是在最上面,就是說在所有參數的最後面,最後壓入的參數在最下面,結構上看起來是第一個,所以最後壓入的參數總是能夠被函數找到,因為它就在堆棧指針的上方。printf的第一個被找到的參數就是那個字元指針,就是被雙引號括起來的那一部分,函數通過判斷字元串里控制參數的個數來判斷參數個數及數據類型,通過這些就可算出數據需要的堆棧指針的偏移量了,下面給出printf("%d,%d",a,b);(其中a、b都是int型的)的匯編代碼.

.section
.data
string out = "%d,%d"
push b //最後的先壓入棧中
push a //最先的後壓入棧中
push $out//參數控制的那個字元串常量是最後被壓入的
call printf

你會看到,參數是最後的先壓入棧中,最先的後壓入棧中,參數控制的那個字元串常量是最後被壓入的,所以這個常量總是能被找到的。

通常情況下函數可變參數表的長度是已知的,通過num參數傳入,這種函數比較容易實現。

㈤ C語言調用可變參數的函數如printf之類的,或者自己定義的函數,如何在函數中確定參數的個數呢

printf按照格式化字元串來讀取

printf("%d%s%d",略); %d%s%d為格式

自定義變參函數,自己定義的解析處理,從va_list 裡面取

㈥ c語言如何定義以數據類型為形參的函數

unsigned int Fun_a(int,int); //聲明
unsigned int Fun_a(int aa,int bb) //定義

{
return (aa+bb);
}

聲明和定義是不一樣的,定義的時候是要有參數名的,聲明的時候可以去掉參數名。

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

一個簡單的例子

voidsimple_va_fun(inti,...)
{
va_listarg_ptr;
intj=0;

va_start(arg_ptr,i);
j=va_arg(arg_ptr,int);
va_end(arg_ptr);
printf("i=%dj=%dn",i,j);
return;
}
intmain()
{
simple_va_fun(1);
simple_va_fun(1,2);
simple_va_fun(1,200);
return0;
}

㈧ 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語言函數中的參數(實參、形參)

不知道函數調用原理的話,很難說得清楚的。粗略的說在C中函數其實是分成三個部分,分別是聲明、實現和使用。聲明就是告訴C有這么個函數,實現就是這個函數的完整代碼,使用則是調用這個函數幫你做運算或者是做事情。為了讓函數能做更多的事情,就需要一種方法能向函數傳遞性息,最可靠、最方便的方法就是參數傳遞,C就是這樣做的。參數傳遞也不是簡單的一件事情,首先在調用者和被調用者之間得有個約定,大家約定好了參數放什麼地方,如何使用,這個就稱為調用約定。現在我們回過頭來看什麼叫實參和形參。由上面的敘述可以看到,函數其實有一定的獨立性的,參數是在調用約定下放在指定地方供函數使用的,在我們實現函數的時候,實際的參數是什麼我們還不知道,但我們知道有多少參數,分別是什麼數據類型的和放在什麼地方(順序),這個是由調用約定來保證的。我們知道的這些就是形式的或者說是邏輯的,我們在實現函數(編寫函數體)的時候需要給他們命名,以便使用,這些在函數實現的時候命名的形式上的參數就是形式參數,簡稱形參。而在實際調用發生的時候,調用者會將實際的參數放在約定好了的地方,這個實際參數簡稱實參。函數被運行的時候實參和形參形成了一一對應,對形參的操作就變成了對實參的操作。

對調用約定還有需要說明的就是,現在常用的調用約定都是傳值的,也就是說只是傳遞了一個副本,這樣做的結果就是你對形參的操作不會被傳遞出來。
是否可以解決您的問題?

㈩ C語言的變參技術,va_start,va_arg,va_end這幾個函數怎麼用

#include <stdarg.h> // 必須包含的頭文件

int Add(int start,...) // ...是作為佔位符
{
va_list arg_ptr; // 定義變參起始指針
int sum=0; // 定義變參的和
int nArgValue =start; //

va_start(arg_ptr,start); // arg_ptr指向第一個變參
do
{
sum+=nArgValue; // 求和
nArgValue = va_arg(arg_ptr,int); // arg_ptr指向下一個變參
}
while(nArgValue != 0); // 判斷結束條件;結束條件是自定義為=0時結束

va_end(arg_ptr); // 復位指針
return sum;
}

函數的調用方法為Add(1,2,3,0);這樣,必須以0結尾,因為變參函數結束的判斷條件就是讀到0停止。

解釋:

所使用到的宏:
void va_start( va_list arg_ptr, prev_param );
type va_arg( va_list arg_ptr, type );
void va_end( va_list arg_ptr );

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)) )
#define va_end(ap) ( ap = (va_list)0 )

1、首先把va_list被定義成char*,這是因為在我們目前所用的PC機上,字元指針類型可以用來存儲內存單元地址。而在有的機器上va_list是被定義成void*的

2、定義_INTSIZEOF(n)主要是為了某些需要內存的對齊的系統.這個宏的目的是為了得到最後一個固定參數的實際內存大小。在我的機器上直接用sizeof運算符來代替,對程序的運行結構也沒有影響。(後文將看到我自己的實現)。

3、va_start的定義為 &v+_INTSIZEOF(v) ,這里&v是最後一個固定參數的起始地址,再加上其實際佔用大小後,就得到了第一個可變參數的起始內存地址。所以我們運行va_start(ap, v)以後,ap指向第一個可變參數在的內存地址,有了這個地址,以後的事情就簡單了。

這里要知道兩個事情:
⑴在intel+windows的機器上,函數棧的方向是向下的,棧頂指針的內存地址低於棧底指針,所以先進棧的數據是存放在內存的高地址處。
(2)在VC等絕大多數C編譯器中,默認情況下,參數進棧的順序是由右向左的,因此,參數進棧以後的內存模型如下圖所示:最後一個固定參數的地址位於第一個可變參數之下,並且是連續存儲的。
|--------------------------|
| 最後一個可變參數 | ->高內存地址處
|--------------------------|
|--------------------------|
| 第N個可變參數 | ->va_arg(arg_ptr,int)後arg_ptr所指的地方,
| | 即第N個可變參數的地址。
|--------------- |
|--------------------------|
| 第一個可變參數 | ->va_start(arg_ptr,start)後arg_ptr所指的地方
| | 即第一個可變參數的地址
|--------------- |
|------------------------ --|
| |
| 最後一個固定參數 | -> start的起始地址
|-------------- -| .................
|-------------------------- |
| |
|--------------- | -> 低內存地址處

(4) va_arg():有了va_start的良好基礎,我們取得了第一個可變參數的地址,在va_arg()里的任務就是根據指定的參數類型取得本參數的值,並且把指針調到下一個參數的起始地址。
因此,現在再來看va_arg()的實現就應該心中有數了:
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
這個宏做了兩個事情,
①用用戶輸入的類型名對參數地址進行強制類型轉換,得到用戶所需要的值
②計算出本參數的實際大小,將指針調到本參數的結尾,也就是下一個參數的首地址,以便後續處理。

(5)va_end宏的解釋:x86平台定義為ap=(char*)0;使ap不再 指向堆棧,而是跟NULL一樣.有些直接定義為((void*)0),這樣編譯器不會為va_end產生代碼,例如gcc在linux的x86平台就是這樣定義的. 在這里大家要注意一個問題:由於參數的地址用於va_start宏,所以參數不能聲明為寄存器變數或作為函數或數組類型. 關於va_start, va_arg, va_end的描述就是這些了,我們要注意的 是不同的操作系統和硬體平台的定義有些不同,但原理卻是相似的.