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 type
in der bar
Funktion aus. Die identische Aussage ist in Ordnung foo
.
Es scheint, dass der Typ eines Agumentes des Typs va_list
nicht 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 bar
Funktion. Mit GCC _Static_assert
schlägt das fehl. Das gleiche kann auch in C ++ mit declytpe
und getestet werden std::is_same
.
Ich möchte die Adresse des va_list vl
Arguments von nehmen bar
und 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 main
und 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_list
und diesen Zeiger an eine andere Funktion zu übergeben
Warum ist dies nicht möglich, wenn va_list
es 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 bar
mithilfe 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 vl
auf diese Funktion übergeben. Ich werde die Frage bearbeiten, um sie anzugeben.
va_list
va_copy
Ansatz, 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
.