有關(guān)VA_LIST的用法
分類:
Symbian智能手機(jī)程序設(shè)計(jì)編程經(jīng)驗(yàn)VA_LIST 是在C語言中解決變參問題的一組宏
VA_LIST的用法:
(1)首先在函數(shù)里定義一具VA_LIST型的變量,這個(gè)變量是指向參數(shù)的指針
(2)然后用VA_START宏初始化變量剛定義的VA_LIST變量,這個(gè)宏的第二個(gè)參數(shù)是第一個(gè)可變參數(shù)的前一個(gè)參數(shù),是一個(gè)固定的參數(shù)。
(3)然后用VA_ARG返回可變的參數(shù),VA_ARG的第二個(gè)參數(shù)是你要返回的參數(shù)的類型。
(4)最后用VA_END宏結(jié)束可變參數(shù)的獲取。然后你就可以在函數(shù)里使用第二個(gè)參數(shù)了。如果函數(shù)有多個(gè)可變參數(shù)的,依次調(diào)用VA_ARG獲取各個(gè)參數(shù)。
VA_LIST在編譯器中的處理:
(1)在運(yùn)行VA_START(ap,v)以后,ap指向第一個(gè)可變參數(shù)在堆棧的地址。
(2)VA_ARG()取得類型t的可變參數(shù)值,在這步操作中首先apt = sizeof(t類型),讓ap指向下一個(gè)參數(shù)的地址。然后返回ap-sizeof(t類型)的t類型*指針,這正是第一個(gè)可變參數(shù)在堆棧里的地址。然后用*取得這個(gè)地址的內(nèi)容。
(3)VA_END(),X86平臺定義為ap = ((char*)0),使ap不再指向堆棧,而是跟NULL一樣,有些直接定義為((void*)0),這樣編譯器不會(huì)為VA_END產(chǎn)生代碼,例如gcc在Linux的X86平臺就是這樣定義的。
要注意的是:由于參數(shù)的地址用于VA_START宏,所以參數(shù)不能聲明為寄存器變量,或作為函數(shù)或數(shù)組類型。
使用VA_LIST應(yīng)該注意的問題:
(1)因?yàn)関a_start, va_arg, va_end等定義成宏,所以它顯得很愚蠢,可變參數(shù)的類型和個(gè)數(shù)完全在該函數(shù)中由程序代碼控制,它并不能智能地識別不同參數(shù)的個(gè)數(shù)和類型. 也就是說,你想實(shí)現(xiàn)智能識別可變參數(shù)的話是要通過在自己的程序里作判斷來實(shí)現(xiàn)的.
(2)另外有一個(gè)問題,因?yàn)榫幾g器對可變參數(shù)的函數(shù)的原型檢查不夠嚴(yán)格,對編程查錯(cuò)不利.不利于我們寫出高質(zhì)量的代碼。
小結(jié):可變參數(shù)的函數(shù)原理其實(shí)很簡單,而VA系列是以宏定義來定義的,實(shí)現(xiàn)跟堆棧相關(guān)。我們寫一個(gè)可變函數(shù)的C函數(shù)時(shí),有利也有弊,所以在不必要的場合,我們無需用到可變參數(shù),如果在C++里,我們應(yīng)該利用C++多態(tài)性來實(shí)現(xiàn)可變參數(shù)的功能,盡量避免用C語言的方式來實(shí)現(xiàn)。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報(bào)。