



全文預(yù)覽已結(jié)束
下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
C語言可變參數(shù)研究作者: 來源:zz 發(fā)表時(shí)間:2006-11-16 瀏覽次數(shù): 364 字號(hào):大 中 小一 何謂可變參數(shù)int printf( const char* format, .);這是使用過C語言的人所再熟悉不過的printf函數(shù)原型,它的參數(shù)中就有固定參數(shù)format和可變參數(shù)(用”表示). 而我們又可以用各種方式來調(diào)用printf,如:printf(%d,value);printf(%s,str);printf(the number is %d ,string is:%s, value, str);二.實(shí)現(xiàn)原理C語言用宏來處理這些可變參數(shù)。這些宏看起來很復(fù)雜,其實(shí)原理挺簡單,就是根據(jù)參數(shù)入棧的特點(diǎn)從最靠近第一個(gè)可變參數(shù)的固定參數(shù)開始,依次獲取每個(gè)可變參數(shù)的地址。下面我們來分析這些宏。在VC中的stdarg.h頭文件中,針對(duì)不同平臺(tái)有不同的宏定義,我們選取X86平臺(tái)下的宏定義:typedef char *va_list;/*把va_list被定義成char*,這是因?yàn)樵谖覀兡壳八玫腜C機(jī)上,字符指針類型可以用來存儲(chǔ)內(nèi)存單元地址。而在有的機(jī)器上va_list是被定義成void*的*/#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & (sizeof(int) - 1) )/*_INTSIZEOF (n)宏是為了考慮那些內(nèi)存地址需要對(duì)齊的系統(tǒng),從宏的名字來應(yīng)該是跟sizeof(int)對(duì)齊。一般的sizeof(int)=4,也就是參數(shù)在內(nèi)存中的地址都為4的倍數(shù)。比如,如果sizeof(n)在14之間,那么_INTSIZEOF(n)4;如果sizeof(n)在58之間,那么 _INTSIZEOF(n)=8。*/#define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) )/*va_start 的定義為 &v+_INTSIZEOF(v) ,這里&v是最后一個(gè)固定參數(shù)的起始地址,再加上其實(shí)際占用大小后,就得到了第一個(gè)可變參數(shù)的起始內(nèi)存地址。所以我們運(yùn)行va_start (ap, v)以后,ap指向第一個(gè)可變參數(shù)在的內(nèi)存地址*/#define va_arg(ap,t) ( *(t *)(ap += _INTSIZEOF(t) - _INTSIZEOF(t) )/*這個(gè)宏做了兩個(gè)事情,用用戶輸入的類型名對(duì)參數(shù)地址進(jìn)行強(qiáng)制類型轉(zhuǎn)換,得到用戶所需要的值計(jì)算出本參數(shù)的實(shí)際大小,將指針調(diào)到本參數(shù)的結(jié)尾,也就是下一個(gè)參數(shù)的首地址,以便后續(xù)處理。*/#define va_end(ap) ( ap = (va_list)0 )/*x86 平臺(tái)定義為ap=(char*)0;使ap不再指向堆棧,而是跟NULL一樣.有些直接定義為(void*)0),這樣編譯器不會(huì)為va_end產(chǎn)生代碼,例如gcc在linux的x86平臺(tái)就是這樣定義的. 在這里大家要注意一個(gè)問題:由于參數(shù)的地址用于va_start宏,所以參數(shù)不能聲明為寄存器變量或作為函數(shù)或數(shù)組類型. */以下再用圖來表示:在VC等絕大多數(shù)C編譯器中,默認(rèn)情況下,參數(shù)進(jìn)棧的順序是由右向左的,因此,參數(shù)進(jìn)棧以后的內(nèi)存模型如下圖所示:最后一個(gè)固定參數(shù)的地址位于第一個(gè)可變參數(shù)之下,并且是連續(xù)存儲(chǔ)的。|最后一個(gè)可變參數(shù) | -高內(nèi)存地址處|.|第N個(gè)可變參數(shù) | -va_arg(arg_ptr,int)后arg_ptr所指的地方,| | 即第N個(gè)可變參數(shù)的地址。| |.|第一個(gè)可變參數(shù) | -va_start(arg_ptr,start)后arg_ptr所指的地方| | 即第一個(gè)可變參數(shù)的地址| | | |最后一個(gè)固定參數(shù) | - start的起始地址| | .| | | |- 低內(nèi)存地址處三.printf研究下面是一個(gè)簡單的printf函數(shù)的實(shí)現(xiàn),參考了中的156頁的例子,讀者可以結(jié)合書上的代碼與本文參照。#include stdio.h#include stdlib.hvoid myprintf(char* fmt, .) /一個(gè)簡單的類似于printf的實(shí)現(xiàn),/參數(shù)必須都是int 類型 char* pArg=NULL; /等價(jià)于原來的va_list char c; pArg = (char*) &fmt; /注意不要寫成p = fmt !因?yàn)檫@里要對(duì)/參數(shù)取址,而不是取值 pArg += sizeof(fmt); /等價(jià)于原來的va_start do c =*fmt; if (c != %) putchar(c); /照原樣輸出字符 else /按格式字符輸出數(shù)據(jù) switch(*+fmt) case d: printf(%d,*(int*)pArg); break; case x: printf(%#x,*(int*)pArg); break; default: break; pArg += sizeof(int); /等價(jià)于原來的va_arg +fmt; while (*fmt != 0); pArg = NULL; /等價(jià)于va_end return;int main(int argc, char* argv) int i = 1234; int j = 5678; myprintf(the first test:i=%d,i,j); myprintf(the secend test:i=%d; %x;j=%d;,i,0xabcd,j); system(pause); return 0;在intel+win2k+vc6的機(jī)器執(zhí)行結(jié)果如下:the first test:i=1234the secend test:i=1234; 0xabcd;j=5678;四.應(yīng)用求最大值:#include /不定數(shù)目參數(shù)需要的宏int max(int n,int num,.) va_list x;/說明變量x va_start(x,num);/x被初始化為指向num后的第一個(gè)參數(shù) int m=num; for(int i=1;i /將變量x所指向的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 餐飲行業(yè)員工勞動(dòng)合同續(xù)簽及競(jìng)業(yè)限制合同
- 居住小區(qū)24小時(shí)安保服務(wù)協(xié)議
- 企業(yè)團(tuán)隊(duì)協(xié)作課件
- 烈士別墅拆除方案
- 餐飲企業(yè)員工勞動(dòng)合同續(xù)簽與解除合同
- 高效環(huán)保廠房及配套設(shè)施轉(zhuǎn)讓及運(yùn)營維護(hù)協(xié)議
- 地面養(yǎng)護(hù)實(shí)施方案
- 突發(fā)事件面試題及答案
- 泰州學(xué)院面試題及答案
- 油品類考試題及答案
- 黨課課件含講稿:《關(guān)于加強(qiáng)黨的作風(fēng)建設(shè)論述摘編》輔導(dǎo)報(bào)告
- 國家開放大學(xué)行管??啤侗O(jiān)督學(xué)》期末紙質(zhì)考試總題庫2025春期版
- DL∕T 5622-2021 太陽能熱發(fā)電廠儲(chǔ)熱系統(tǒng)設(shè)計(jì)規(guī)范
- 物理化學(xué)實(shí)驗(yàn):實(shí)驗(yàn)12 膠體的制備和電泳
- 高中物理選修 分子動(dòng)理論
- 領(lǐng)軍人才選拔試題答案
- CNC數(shù)控車床操作指導(dǎo)書
- 管道施工主要質(zhì)量保證措施及通病防治措施
- 失火罪消防責(zé)任事故罪消防刑事案件移送移交報(bào)告
- 斯巴達(dá)勇士賽
- 住院醫(yī)師規(guī)范化培訓(xùn)臨床小講課指南(2021年版)
評(píng)論
0/150
提交評(píng)論