前言:
10年積累的成都做網(wǎng)站、成都網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有興安盟免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
有時候我們需要一個函數(shù)接口可以支持可變參數(shù)以提高其泛化能力,比如說定義一個求和函數(shù),對傳入的所有參數(shù)進(jìn)行求和并返回,C語言提供了一種可變參數(shù)的方式來幫助我們實現(xiàn)。
原理:
函數(shù)參數(shù)是從右向左線性連續(xù)依次入棧,如果我們可以知道可變參數(shù)列表的前一個參數(shù)的地址和類型,就可以得知可變參數(shù)列表的首地址,進(jìn)而根據(jù)每個參數(shù)的類型取出相應(yīng)的數(shù)據(jù)。簡單來說就是將棧里面的數(shù)據(jù),按照指定類型的大小,依次取出。
具體實現(xiàn):
步驟解析:
#include
void
foo(int
x,
int
y,
int
z)
{
printf("x
=
%d
at
[%x]n",
x,
x);
printf("y
=
%d
at
[%x]n",
y,
y);
printf("z
=
%d
at
[%x]n",
z,
z);
}
int
main(int
argc,
char
*argv[])
{
foo(100,
200,
300);
return
0;
}
運行結(jié)果:
x
=
100
at
[bfe28760]
y
=
200
at
[bfe28764]
z
=
300
at
[bfe28768]
c程序棧底為高地址,棧頂為低地址,因此上面的實例可以說明函數(shù)參數(shù)入棧順序的確是從右至左的??傻降诪槭裁茨兀坎榱艘恢毙┪墨I(xiàn)得知,參數(shù)入棧順序是和具體編譯器實現(xiàn)相關(guān)的。比如,pascal語言中參數(shù)就是從左到右入棧的,有些語言中還可以通過修飾符進(jìn)行指定,如visual
c++.即然兩種方式都可以,為什么c語言要選擇從右至左呢?
進(jìn)一步發(fā)現(xiàn),pascal語言不支持可變長參數(shù),而c語言支持這種特色,正是這個原因使得c語言函數(shù)參數(shù)入棧順序為從右至左。具體原因為:c方式參數(shù)入棧順序(從右至左)的好處就是可以動態(tài)變化參數(shù)個數(shù)。通過棧堆分析可知,自左向右的入棧方式,最前面的參數(shù)被壓在棧底。除非知道參數(shù)個數(shù),否則是無法通過棧指針的相對位移求得最左邊的參數(shù)。這樣就變成了左邊參數(shù)的個數(shù)不確定,正好和動態(tài)參數(shù)個數(shù)的方向相反。
因此,c語言函數(shù)參數(shù)采用自右向左的入棧順序,主要原因是為了支持可變長參數(shù)形式。換句話說,如果不支持這個特色,c語言完全和pascal一樣,采用自左向右的參數(shù)入棧方式
可變參數(shù)是用于調(diào)用函數(shù)時,不知道參數(shù)的個數(shù)及類型的一種場合,最經(jīng)典最常用的是
int
printf(const
char
*format[,
argument,
...]);
它后面的參數(shù)類型及數(shù)量都是可變的
如
printf("%d",x);
//一個int參數(shù)
printf("%d%d%s\n",x,y,z);
//三個參數(shù),前兩個為int,后面的為char
*