日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

解析可变参数函数的实现原理(printf,scanf)

發布時間:2023/12/9 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解析可变参数函数的实现原理(printf,scanf) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From: http://hi.baidu.com/huifeng00/blog/item/085e8bd198f46ed3a8ec9a0b.html

?

學習C的語言的時候,肯定接觸到標準輸出和標準輸入函數。

這個函數給人的感覺很強大,因為它很另類,就是這個函數的參數是可變的。

下面是一個自己編寫的可變參數的函數,它的功能是求和。如下

#include <stdio.h>
#include <stdarg.h>
int sum(int data,...)
{
??? int i=data,s=0;
va_list vl;
va_start(vl,data);
while(i!=-1)
{
?? s+=i;
?? i=va_arg(vl,int);
}
va_end(vl);
return s;
}
int main()
{
??? int s=sum(1,2,3,4,5,-1);
printf("sum = %d\n",s);
return 0;
}

程序如上,注意以下幾點就可以編寫可變參數的函數了。

1.聲明

int sum(int data,...)

它的末尾是以...結束的,表示是可變參數函數。

2.正確使用

va_list

va_start,va_arg,va_end

如上,就可以編寫可變參數函數了。

不過大多數初級學者可能對

va_list

va_start,va_arg,va_end

望而卻步,認為他們很神秘。

其實他們也是很基礎的C知識,只是被包裝了。

C中包裝的方法,有 typedef,#define

例如你把int包裝成ID

typedef int ID;

其實

va_list

va_start,va_arg,va_end

他們也是包裝得到的。

va_list 就是一個指針類型。

va_start,va_arg,va_end,就是3個宏。

下面給出它們在C中的源碼


如上你可以在頭文件stdarg.h中查到,本文是針對VC6.0來說的,高版本的編譯器,在vadefs.h,它的定義是

類似的。

不過本文關鍵是說實現的原理:

首先在你調用一個可變參數函數時,例如

上面的

int s=sum(1,2,3,4,5,-1);

這個函數,編譯器會在內存中分配空間存儲這些參數。

根據編譯器中從右至左的順序把參數壓棧。

這里的棧就是常說的存儲局部變量和函數參數的內存空間。

這塊內存空間是連續的。

因此我們只要能找到這塊內存空間的首地址就可以了。然后每讀一個參數,就加上這個參數在內存空間中占

的大小,就是下一個參數的內存地址,就這樣依次就可以得到每一個參數。

下面說下每個標識的含義

1,va_list 就是一個char* 指針,用來記錄這個參數列表在內存中地址。


2,va_start()

例如:va_start(vl,data);這個宏是得到參數列表中第2個參數內存地址。

至于為什么不是第一個,這和寫編譯器的程序員有關,因為它的宏定義,就是說明這個vl,注(vl就是va_list)

指向的就是第2個參數。



如上,v就是第一個參數,ap就是va_list的變量,例如上面的

va_start(vl,data);

很明顯它先得到第一個參數內存地址,然后又加上這個參數的內存大小,就是下個參數的內存地址。

注:因為第一個參數,參數列表中已經給出,所以它得到的是第2個參數的內存地址。

3,va_arg

這個宏的意思,就是取得當前vl所指的參數,并且vl加上這個參數大小,指向下一個參數。

它的定義,明顯說明了這個問題。


它先加上參數類型t的大小,然后,在減去,參數類型t的大小,然后作強制類型轉換(t*),所以t一定要是類

型,不是變量。然后取*得到改地址指向的內存中的數據。

例如實例中的

i=va_arg(vl,int);

第一次調用的時候,它得到就是參數列表中第二個參數的值。

下面依次調用就可以得到第三個,第四個參數的值。。。

4,va_end
這個宏,就比較簡單了。

就是把指針值歸0.讓它指向NULL。

也就是一個指針不用了,就會把它賦值為NULL.


如上明先可以看到

這個宏就是一個賦值語句。

ap=(char*)0;//va_list 就是cha*的別名。

其實只要把4個標識

va_list

va_start,va_arg,va_end

的意思記住了,就可以編寫可變參數的函數。

使用的主要注意

va_start(ap,v)

v是第一個參數。

va_arg(ap,t)

t是你要取得的參數類型。

va_end(ap)

就是把指針ap賦值為0,使他不指向內存的變量。

ap

就是

va_list的一個變量。也就是一個

char *類型的變量。

到此,我想你應該對可變參數函數的實現原理有了一定的了解,起碼應該有了形象的了解吧。

coder:huifeng00

總結

以上是生活随笔為你收集整理的解析可变参数函数的实现原理(printf,scanf)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。