Ich versuche, ein char-Array in C zu erstellen, um es mit den Ziffern eines int zu füllen, aber der int kann aus einer beliebigen Anzahl von Ziffern bestehen.
Ich verwende eine erstellte Funktion namens getDigits(int num)
, die eine Anzahl von Ziffern zurückgibt, die int hat.
, aber wenn ich mit gcc kompiliere, gibt es zurück:
error: variable-sized object may not be initialized
Ich habe alles versucht. Wenn ich es als char fileSizeStr[5] = "";
deklariere, funktioniert es. Ich kann sehen, dass das Problem steigt, wenn ich versuche, die Puffergröße dynamisch zu deklarieren, aber ich würde wirklich gerne wissen, ob dies ein Weg ist, dies zu erreichen.
Das Problem ist genau so, wie Ihr Compiler es Ihnen sagt; Sie dürfen keine VLAs initialisieren. Zack gab eine offensichtliche Lösung in den Kommentaren: Entfernen Sie die Initialisierung. In dieser Antwort finden Sie Arbeitsbeispiele, von denen einige eine Initialisierung erlauben und andere nicht. Mehr dazu finden Sie in Kommentaren. Die folgenden Beispiele sind von den sinnvollsten (IMHO) zu den am wenigsten sinnvollen (mit malloc
) für die Zuweisung von Speicher für Dezimalziffernfolgen, die Zahlen darstellen, angeordnet.
Ich schlage vor, mit demselben Trick zu bestimmen, wie viele Bytes zum Speichern eines int
-Werts als Dezimalziffern erforderlich sind, wie Sie für oktal verwenden würden: Teilen Sie die Gesamtzahl der Bits in int
durch 3 und addieren Sie für jedes Zeichen und NULL Kündigung. digit_count
könnte als ein Präprozessor-Makro wie folgt geschrieben werden:
Wie Sie sehen, ist ein großer Vorteil hier, dass digit_count
für jede Art von Ganzzahl ohne Änderung verwendet werden kann: char
, short
, int
, long
, long long
und Entsprechende unsigned
-Typen.
Ein kleiner Nachteil im Vergleich ist, dass Sie ein paar Bytes Speicher verschwenden, besonders für kleine Werte wie 1
. In vielen Fällen gleicht die Einfachheit dieser Lösung dies aus; Der Code, der zum Zählen der Dezimalziffern zur Laufzeit benötigt wird, belegt mehr Speicherplatz als hier verschwendet wird.
Wenn Sie bereit sind, die Einfachheit und generischen Eigenschaften des obigen Codes wegzuwerfen, und Sie wirklich die Anzahl der Dezimalstellen zählen möchten, gilt Zacks Rat: Entfernen Sie die Initialisierung. Hier ist ein Beispiel:
%Vor% Als Reaktion auf die malloc
-Empfehlungen: Der am wenigsten schreckliche Weg zur Lösung dieses Problems besteht darin, unnötigen Code zu vermeiden (zB Aufrufe an malloc
und später an free
). Wenn Sie das Objekt nicht von einer Funktion zurückgeben müssen, verwenden Sie nicht malloc
! Andernfalls sollten Sie in einem vom Aufrufer bereitgestellten Puffer speichern (über Argumente), damit der Anrufer auswählen kann, welcher Speichertyp verwendet werden soll. Es ist sehr selten, dass dies keine geeignete Alternative zur Verwendung von malloc
ist.
Wenn Sie sich dafür entscheiden, malloc
und free
zu verwenden, tun Sie es jedoch am wenigsten schrecklich. Vermeiden Sie Typumwandlungen auf dem Rückgabewert von malloc
und Multiplikationen von sizeof (char)
(was immer 1 ist). Der folgende Code ist ein Beispiel. Verwenden Sie eine der obigen Methoden, um die Länge zu berechnen:
... und vergiss nicht free(buffer);
, wenn du damit fertig bist.
versuche etwas wie:
%Vor%malloc und calloc werden für die dynamische Zuordnung verwendet.
Für mein Geld gibt es eine Lösung, die unerwähnt geblieben ist, die aber tatsächlich einfacher ist als alle anderen. Es gibt eine kombinierte Allokationsversion von sprintf namens "asprintf", die unter Linux und den meisten BSD-Varianten verfügbar ist. Es bestimmt die erforderliche Größe, mallocs den Speicher und gibt die gefüllte Zeichenfolge in das erste Argument zurück.
%Vor%Die Verwendung eines Stack-zugewiesenen Arrays beseitigt zwar die Notwendigkeit für das Free, aber das macht es völlig überflüssig, die Größe jemals separat zu berechnen.