Wie funktioniert die bestimmte C-Funktion?

8

Ich versuche C zu lernen und bin schon sehr verwirrt.

In den von mir verwendeten OOP-Sprachen gibt es die Möglichkeit, das Überladen von Methoden durchzuführen, wobei dieselbe Funktion verschiedene Parametertypen haben und den jeweils passenden aufrufen kann.

Nun in C weiß ich, dass dies nicht der Fall ist, also kann ich das folgende Problem nicht herausfinden, wie printf () funktioniert.

Zum Beispiel:

%Vor%

Nun, da C das Überladen von Funktionen nicht unterstützt, wie kann printf eine beliebige Anzahl von Argumenten beliebiger Art verarbeiten und dann korrekt mit ihnen arbeiten?

Ich habe versucht, die Funktion printf () zu finden, indem ich das glibc-Quellpaket herunterlade, aber ich kann es anscheinend finden, obwohl ich weiter nachsehen werde.

Könnte jemand hier erklären, wie C die obige Aufgabe erfüllt?

    
Pike Man 16.01.2012, 17:32
quelle

3 Antworten

11

C unterstützt eine Art von Funktionssignaturen mit dem Namen "varargs", die "variable (Anzahl von) Argumente" bedeuten. Eine solche Funktion muss mindestens ein erforderliches Argument haben. Im Fall von printf ist die Formatzeichenfolge ein erforderliches Argument.

Wenn Sie eine C-Funktion aufrufen, werden die Argumente auf einer stackbasierten Maschine im Allgemeinen von rechts nach links auf den Stapel geschoben. Auf diese Weise ist das erste Argument für die Funktion das, das auf der "Spitze" des Stapels unmittelbar nach der Rückkehradresse gefunden wird.

Es sind C-Makros definiert, mit denen Sie die Variablenargumente abrufen können.

Die wichtigsten Punkte sind:

  • Es gibt keine Typsicherheit für die variablen Argumente. Im Fall von printf() , wenn die Formatzeichenfolge falsch ist, liest der Code ungültige Ergebnisse aus dem Speicher und stürzt möglicherweise ab.
  • Die Variablenargumente werden durch einen Zeiger gelesen, der durch den Speicher mit diesen Argumenten inkrementiert wird.
  • Der Argumentzeiger muss mit va_start initialisiert, mit va_arg erhöht und mit va_end .
  • freigegeben werden

Ich habe eine Menge Code gepostet, den Sie vielleicht in der verwandten Frage interessant finden:

Beste Möglichkeit, eine va_list für die spätere Verwendung in C / C ++ zu speichern

Hier ist ein Skelett von printf() , das nur ganze Zahlen formatiert ("% d"):

%Vor%     
Heath Hunnicutt 16.01.2012, 18:15
quelle
4

Intern wird printf (zumindest normalerweise) einige Makros von stdarg.h verwenden. Die allgemeine Idee ist (eine stark erweiterte Version von) etwa so:

%Vor%

Das Ausarbeiten erfordert ziemlich viel Arbeit - es geht um Feldbreite, Genauigkeit, mehr Konvertierungen usw. Dies ist jedoch genug, um zumindest einen Eindruck davon zu vermitteln, wie Sie unterschiedliche Argumente unterschiedlicher Typen in Ihrem System abrufen Funktion.

    
Jerry Coffin 16.01.2012 17:44
quelle
2

(Vergessen Sie nicht, dass Sie, wenn Sie gcc (und g ++?) verwenden, -Wformat in den Compileroptionen übergeben können, damit der Compiler überprüft, ob die Typen der Argumente mit der Formatierung übereinstimmen. Ich hoffe andere Compiler haben ähnliche Optionen.)

  

Könnte jemand hier erklären, wie C die obige Aufgabe erfüllt?

Blinder Glaube. Es setzt voraus, dass Sie sichergestellt haben, dass die Typen der Argumente perfekt mit den entsprechenden Buchstaben in Ihrer Formatzeichenfolge übereinstimmen. Wenn printf aufgerufen wird, werden alle Argumente in binärer Form dargestellt, unzeremoniell verkettet und effektiv als einzelnes großes Argument an printf übergeben. Wenn sie nicht übereinstimmen, haben Sie Probleme. Wenn printf durch die Formatzeichenfolge iteriert, wird es jedes Mal, wenn es %d sieht, 4 Bytes von den Argumenten nehmen (angenommen 32-Bit, es wären natürlich 8 Bytes für 64-Bit-Ints) und es wird sie als interpretieren eine Ganzzahl.

Vielleicht haben Sie nun tatsächlich double übergeben (normalerweise doppelt so viel Speicher wie ein int ). In diesem Fall nimmt printf nur 32 dieser Bits und stellt sie als Integer dar. Dann nimmt das nächste Formatfeld (vielleicht ein %d ) den Rest des Double.

Wenn also die Typen nicht perfekt zusammenpassen, werden Sie sehr unlesbare Daten erhalten. Und wenn Sie Pech haben, haben Sie undefiniertes Verhalten.

    
Aaron McDaid 16.01.2012 17:49
quelle

Tags und Links