In meinen C-Programmen benötige ich häufig eine Möglichkeit, eine Zeichenfolgendarstellung meiner ADTs zu erstellen. Auch wenn ich die Zeichenfolge nicht drucken muss, um sie in irgendeiner Weise auf dem Bildschirm anzuzeigen, ist es ordentlich, eine solche Methode zum Debuggen zu haben. Diese Art von Funktion kommt also oft vor.
char * mytype_to_string( const mytype_t *t );
Mir ist tatsächlich klar, dass ich hier (mindestens) drei Optionen habe, um den Speicher für die Rückgabe der Zeichenfolge zu verwalten.
Alternative 1: Speichern der Rückgabezeichenfolge in einem statischen Zeichenarray in der Funktion. Ich brauche nicht viel nachzudenken, außer dass die Zeichenfolge bei jedem Aufruf überschrieben wird. Was in manchen Fällen ein Problem sein kann.
Alternative 2: Ordnen Sie die Zeichenfolge auf dem Heap mit malloc innerhalb der Funktion zu. Wirklich ordentlich, da ich dann nicht an die Größe eines Puffers oder das Überschreiben denken muss. Ich muss jedoch daran denken, die Zeichenfolge freizugeben (), wenn ich fertig bin, und dann muss ich auch einer temporären Variablen zuweisen, damit ich sie freigeben kann. und dann ist die Heap-Zuweisung wirklich viel langsamer als die Stapelzuweisung. Seien Sie daher ein Engpass, wenn dies in einer Schleife wiederholt wird.
Alternative 3: Übergeben Sie den Zeiger auf einen Puffer und lassen Sie den Aufrufer diesen Puffer zuweisen. Mögen:
char * mytype_to_string( const mytype_t *mt, char *buf, size_t buflen );
Dies bringt dem Anrufer mehr Aufwand. Ich stelle auch fest, dass diese Alternative mir eine andere Option in der Reihenfolge der Argumente gibt. Welches Argument sollte ich zuerst und zuletzt haben? (eigentlich sechs Möglichkeiten)
Also, was soll ich bevorzugen? Warum? Gibt es einen ungeschriebenen Standard unter C-Entwicklern?
quelle
sysctlbyname
unter OS X und iOSAntworten:
Die Methoden, die ich am meisten gesehen habe, sind 2 und 3.
Der vom Benutzer bereitgestellte Puffer ist eigentlich recht einfach zu verwenden:
Die meisten Implementierungen geben jedoch die Menge des verwendeten Puffers zurück.
Option 2 ist langsamer und gefährlich, wenn dynamisch verknüpfte Bibliotheken verwendet werden, in denen möglicherweise unterschiedliche Laufzeiten (und unterschiedliche Heaps) verwendet werden. Sie können also nicht freigeben, was in einer anderen Bibliothek gespeichert wurde. Dies erfordert dann eine
free_string(char*)
Funktion, um damit umzugehen.quelle
printf("MyType: %s\n", mytype_to_string( mt, buf, sizeof(buf));
und daher möchte ich nicht die verwendete Länge zurückgeben, sondern den Zeiger auf die Zeichenfolge. Der dynamische Bibliothekskommentar ist wirklich wichtig.sizeof(buffer) - 1
, um den\0
Terminator zufrieden zu stellen ?snprintf
verwendet funktioniert .Zusätzliche Designidee für # 3
mytype
Geben Sie nach Möglichkeit auch die maximale Größe an, die für dieselbe .h-Datei wie erforderlich istmytype_to_string()
.Jetzt kann der Benutzer entsprechend codieren.
Bestellen
Die Größe der Arrays ermöglicht, wenn zuerst, VLA-Typen.
Nicht so wichtig bei einer Dimension, aber nützlich bei 2 oder mehr.
Ich erinnere mich, dass das Lesen der Größe zuerst eine bevorzugte Redewendung im nächsten C ist. Ich muss diese Referenz finden ...
quelle
Als Ergänzung zu @ ratchetfreaks hervorragender Antwort möchte ich darauf hinweisen, dass Alternative Nr. 3 einem ähnlichen Paradigma / Muster folgt wie Standardfunktionen der C-Bibliothek.
Zum Beispiel
strncpy
.Das Befolgen des gleichen Paradigmas würde dazu beitragen, die kognitive Belastung für neue Entwickler (oder sogar Ihr zukünftiges Selbst) zu verringern, wenn diese Ihre Funktion nutzen müssen.
Der einzige Unterschied zu dem, was Sie in Ihrem Beitrag haben, besteht darin, dass das
destination
Argument in den C-Bibliotheken in der Regel zuerst in der Argumentliste aufgeführt wird. So:quelle
Neben der Tatsache, dass Sie einen schlechten Code-Geruch vorschlagen, klingt Alternative 3 für mich am besten. Ich denke auch wie @ gnasher729, dass Sie die falsche Sprache verwenden.
quelle
Um ehrlich zu sein, möchten Sie möglicherweise zu einer anderen Sprache wechseln, in der das Zurückgeben einer Zeichenfolge keine komplexe, arbeitsintensive und fehleranfällige Operation ist.
Sie könnten C ++ oder Objective-C in Betracht ziehen, bei denen Sie 99% Ihres Codes unverändert lassen könnten.
quelle