Ich experimentiere mit variablen Argumenten in C ++, indem ich va_args verwende. Die Idee ist nützlich, und in der Tat habe ich viel in C # über die Params-Funktionalität verwendet. Eine Sache, die mich frustriert, ist der folgende Auszug über va_args, oben:
Beachten Sie auch, dass va_arg nicht bestimmt, ob das abgerufene Argument das letzte an die Funktion übergebene Argument ist (oder selbst wenn es ein Element nach dem Ende dieser Liste ist).
Ich kann es kaum glauben, dass es keine Möglichkeit gibt, die Anzahl der Variablenargumente programmatisch zu bestimmen, die von dieser Funktion selbst an die Funktion übergeben werden. Ich möchte etwas wie das folgende ausführen:
%Vor%Um es noch einmal zu wiederholen, schlägt die obige Dokumentation vor, dass va_arg nicht bestimmt, ob das abgerufene Argument das letzte in der Liste ist. Aber ich denke, dass diese Informationen in irgendeiner Weise zugänglich sein müssen.
Gibt es einen Standardweg, um dies zu erreichen?
Ich kann es kaum glauben, dass es keine Möglichkeit gibt, die Anzahl der Variablenargumente programmatisch zu bestimmen, die von dieser Funktion selbst an die Funktion übergeben werden.
Trotzdem ist es wahr. C / C ++ platziert keine Markierungen am Ende der Argumentliste, so dass die aufgerufene Funktion wirklich nicht weiß, wie viele Argumente sie empfängt. Wenn Sie das Ende der Argumente markieren müssen, müssen Sie dies selbst tun, indem Sie am Ende der Liste eine Art Markierung setzen.
Die aufgerufene Funktion hat auch keine Vorstellung von den Typen oder Größen der bereitgestellten Argumente. Deshalb müssen printf
und freunde Sie dazu zwingen, den genauen Datentyp des zu interpolierenden Werts in der Formatzeichenfolge anzugeben, und auch, warum Sie ein Programm abstürzen lassen können, indem Sie printf mit einer fehlerhaften Formatzeichenfolge aufrufen.
Beachten Sie, dass die Parameterübergabe von der ABI für eine bestimmte Plattform und nicht von den C ++ / C-Standards angegeben wird. Die ABI muss jedoch zulassen, dass die C ++ / C-Standards implementierbar sind. Zum Beispiel könnte ein ABI Parameter in Registern zur Effizienz übergeben wollen, aber in diesem Fall ist es uU nicht möglich, va_args einfach zu implementieren. Es ist also möglich, dass Argumente auch auf dem Stack schattiert sind. In fast keinem Fall ist der Stack so markiert, dass er das Ende der Argumentliste anzeigt, da die C ++ / C-Standards diese Informationen nicht verfügbar machen müssen und daher unnötiger Overhead wäre.
Die Art und Weise, wie Variablenargumente in C und C ++ funktionieren, ist relativ einfach: Die Argumente werden einfach auf den Stack geschoben, und es liegt in der Verantwortung des Angerufenen, etwas herauszufinden, welche Argumente es gibt. Im Standard gibt es keine Möglichkeit, die Anzahl der Argumente zu bestimmen. Daher wird die Anzahl der Argumente durch einige Kontextinformationen bestimmt, z. B. die Anzahl der Elemente, auf die in einer Formatzeichenfolge verwiesen wird.
Einzelne Compiler können wissen, wie viele Elemente es gibt, aber es gibt keine Standardschnittstelle, um diesen Wert zu erhalten.
Sie können stattdessen jedoch variadische Vorlagen verwenden: Sie können sehr detaillierte Informationen zu den Argumenten bestimmen, die an die Funktion übergeben werden. Die Schnittstelle sieht anders aus und es kann notwendig sein, die Argumente in eine Art von Datenstruktur zu kanalisieren, aber auf der anderen Seite würde sie auch mit Typen funktionieren, die nicht mit variablen Argumenten übergeben werden können.
Nein, ist es nicht. Deshalb sind variable Argumente nicht sicher . Sie sind ein Teil von C, dem die Ausdruckskraft fehlt, um Typsicherheit für "bequeme" variadische Funktionen zu erreichen. Sie müssen mit der Tatsache leben, dass C Konstruktionen enthält, deren Korrektheit von Werten und nicht nur von Typen abhängt. Deshalb ist es eine "unsichere Sprache".
Verwenden Sie keine Variablenargumente in C ++. Es ist eine viel stärkere Sprache, die Ihnen erlaubt, ebenso bequemen Code zu schreiben, der sicher ist.
So sehr Sie sich auch wünschen, dass es wahr ist, es gibt keinen direkten Weg, den Typ oder die Anzahl der Argumente zu kennen, die an variadische Funktionen übergeben werden.
Eine Option besteht darin, eine Markierung am Ende der Argumentenliste zu übergeben, wie z.B. execl ():
%Vor%Ein anderer besteht darin, die Anzahl (und den Typ) von Argumenten explizit zu übergeben, wie bei printf () und seiner Formatzeichenfolge.
Variadic-Funktionen sind daher von Natur aus unsicher, und der geringste Fehler führt dazu, dass Ihr Code versagt. In C ++ gibt es sichere Alternativen, wie das Übergeben eines Vektors. Wenn alle Argumente nicht den gleichen Typ haben, können Sie sie in einen anderen Container wie Boost einbinden :: any .
Die Liste der variablen Argumente ist ein sehr altes Konzept, das von der C-Geschichte von C ++ übernommen wurde. Es stammt aus der Zeit, in der C-Programmierer normalerweise den generierten Assembler-Code im Hinterkopf hatten.
Zu diesem Zeitpunkt hat der Compiler überhaupt nicht überprüft, ob die Daten, die Sie beim Aufruf an eine Funktion übergeben haben, mit den Datentypen übereinstimmen, die die Funktion erwartet. Es lag in der Verantwortung des Programmierers, das richtig zu machen. Wenn zum Beispiel der Aufrufer die Funktion mit einem char
aufgerufen hat und die Funktion ein int
erwartet hat, ist das Programm abgestürzt, obwohl der Compiler sich nicht beschwert hat.
Die heutige Typprüfung verhindert diese Fehler, aber mit einer Variablenargumentliste kehren Sie zu diesen alten Konzepten zurück, einschließlich aller Risiken. Also, benutze es nicht, wenn du es irgendwie vermeiden kannst.
Die Tatsache, dass dieses Konzept mehrere Jahrzehnte alt ist, ist wahrscheinlich der Grund, dass es sich im Vergleich zu modernen Konzepten des sicheren Codes falsch anfühlt.
Tags und Links c++ variadic-functions