Beim Versuch, diesen Code zu kompilieren
#include <stdarg.h>
void bar_ptr(int n, va_list *pvl) {
// do va_arg stuff here
}
void bar(int n, va_list vl) {
va_list *pvl = &vl; // error here
bar_ptr(n, pvl);
}
void foo(int n, ...) {
va_list vl;
va_list *pvl = &vl; // fine here
va_start(vl, n);
bar(n, vl);
va_end(vl);
}
int main() {
foo(3, 1, 2, 3);
return 0;
}
Der GCC-Compiler gibt eine Warnung initialization from incompatible pointer typein der barFunktion aus. Die identische Aussage ist in Ordnung foo.
Es scheint, dass der Typ eines Agumentes des Typs va_listnicht a ist va_list. Dies kann leicht mit einer statischen Behauptung wie getestet werden
_Static_assert(sizeof(vl) == sizeof(va_list), "invalid type");
in der barFunktion. Mit GCC _Static_assertschlägt das fehl. Das gleiche kann auch in C ++ mit declytpeund getestet werden std::is_same.
Ich möchte die Adresse des va_list vlArguments von nehmen barund es als Argument von übergeben bar_ptr, um zu denken, wie in diesem Thread beschrieben . Auf der anderen Seite ist es in Ordnung, bar_ptr(n, pvl)direkt von anzurufen mainund zu ersetzen bar(n, vl).
Gemäß der Fußnote 253 des C11 endgültigen Entwurf ,
Es ist zulässig, einen Zeiger auf a zu erstellen
va_listund diesen Zeiger an eine andere Funktion zu übergeben
Warum ist dies nicht möglich, wenn va_listes als Argument der Funktion definiert ist und nicht im Funktionskörper?
Problemumgehung:
Auch wenn dies die Frage nicht beantwortet, besteht eine mögliche Problemumgehung darin, den Inhalt barmithilfe einer lokalen Kopie des mit va_copy erstellten Arguments zu ändern:
void bar(int n, va_list vl) {
va_list vl_copy;
va_copy(vl_copy, vl);
va_list *pvl = &vl_copy; // now fine here
bar_ptr(n, pvl);
va_end(va_copy);
}
va_list, sondern einen tatsächlichen va_list.
va_list. Angenommen, ich habe eine dritte Funktion void bar_ptr(va_list *pvl);, ich möchte einen Zeiger va_list vlauf diese Funktion übergeben. Ich werde die Frage bearbeiten, um sie anzugeben.
va_list
va_copyAnsatz, den Sie haben, ist die kanonische Lösung für dieses Problem. Ich habe einige frühere Fragen dazu, die dies im Grunde genommen abgeschlossen haben.
va_list.