我有一個關於可變的參數個數幾個問題:可變數字
爲什麼
va_start
,va_arg
,並且va_end
定義爲宏而不是函數?如何
va_start
工作?它是否有權訪問函數調用堆棧並遍歷堆棧直到找到最後指定的參數?
我有一個關於可變的參數個數幾個問題:可變數字
爲什麼va_start
,va_arg
,並且va_end
定義爲宏而不是函數?
如何va_start
工作?它是否有權訪問函數調用堆棧並遍歷堆棧直到找到最後指定的參數?
爲什麼他們是宏覆蓋在Rationale for International Standard—Programming Languages—C在第7.15
可變參數的理由它說:
的va_start並在va_arg必須存在的宏,因爲的va_start使用的參數爲 路過名稱和va_arg使用一個參數,它是數據類型的名稱。
本文How Variable Argument Lists Work in C介紹爲什麼在更詳細,並給出了可能的實現:
typedef char *va_list;
#define va_start(list, param) (list = (va_list)(¶m + sizeof(param)))
#define va_arg(list, type) (*(type *)((list += sizeof(type)) - sizeof(type))
在C++你有很多其他選擇,並Variable number of arguments in C++?可能涵蓋所有的人。
其實va_end
不需要被實現爲宏,都不是,我認爲,確實的va_start(你只需要添加
&
到參數指針傳遞給他們)。
va_end
和va_start
必須imlemented如宏,因爲你不能在所有情況下使用&
,如在評論中指出。
va_arg
必須作爲一個宏,因爲你需要提供一個類型作爲參數傳遞給它,你不能沒有做宏來實現。
va_start
按照你的設想工作:你給它第一個參數,它可以根據該參數的大小計算其他參數的位置,因爲它們在堆棧上都是連續的。
它只是啓動va_list
指向第一個參數(您傳遞給va_start
)的末尾,並在每次使用va_arg
時增加下一個的大小。
va_start
,va_arg
和va_end
通常必須在可變參數函數來完成他們的工作的上下文中執行,因此使得它們的功能會令他們無論是複雜得多,或者(在某些情況下)完全不可能實現的。
它是如何工作的細節留給實施。在典型的情況下,參數可變參數的功能將被推左到右,所以第一個參數將是最接近於堆疊的頂部。爲了得到它,va_arg
只需要知道一個堆棧幀,基本結構如寄信人地址是多大(頂部的說法通常是正確的旁邊)。
'va_start'和'va_end'確實需要在可變參數中使用,是的;但'va_arg'可用於從可變參數函數調用的函數中。由於其他人指出的原因,它通常仍然是一個宏(和/或編譯器內置)。 – torek
我想你應該離開c varaidic論證列表並切換到C++ 11 [variadic templates](http://thenewcpp.wordpress.com/2011/11/23/variadic-templates-part-1-2/ ) – smac89