String Manipulation und Speicherzuweisung - C

8

Ich bin dabei, C. zu lernen. Ich habe eine Methode, die 3 Strings braucht und sie kombiniert, um etwas zu tun. Folgendes war meine erste Implementierung mit einem GCC-Compiler.

%Vor%

Das funktioniert gut. Aber als ich das mit cc -Wall -pedantic -g foo.c -o foo kompiliert habe, habe ich Warnungen wie ISO C90 forbids variable length array ‘combined’ bekommen. MSVC kompilierte diesen Code nicht. Der Code wurde wie folgt geändert:

%Vor%

Fragen

  1. Ist das die korrekte Implementierung?
  2. Wenn Arrays mit variabler Länge nicht Teil des Standards sind, warum hat GCC das implementiert? Wenn der Code nur auf GCC kompiliert werden soll, ist die Verwendung von variablen Arrays eine bessere Alternative als die Verwendung von malloc?
  3. Ich denke, die Daumenregel ist, wenn der Speicherbedarf zur Kompilierzeit bekannt ist, verwenden Sie Arrays, andernfalls verwenden Sie malloc, um den erforderlichen Speicher zuzuordnen. Ist das korrekt?
  4. Mein Code wird voraussichtlich auf GCC und MSVC kompiliert. Ich werde normalerweise auf GCC entwickeln. Also, was sind die Compiler-Flags, die maximale Portabilität gewährleistet? Momentan verwende ich -Wall -pedantic . Soll ich auch -ansi verwenden? Was wären die äquivalenten Flags, die in MSVC verfügbar sind?
  5. Was sind die anderen üblichen Dinge, die beim Schreiben von portablem C-Code zu beachten sind?
Navaneeth K N 07.07.2010, 08:19
quelle

4 Antworten

8
  

Das funktioniert gut. Aber als ich das mit cc -Wall -pedantic -g foo.c -o foo kompilierte, fing ich an, Warnungen wie ISO C90 zu bekommen verbietet variable Längen-Array 'kombiniert'.

Versuchen Sie, mit -std=c99 -Option (gcc) zu kompilieren.

  

MSVC kompilierte diesen Code nicht. Der Code wurde wie folgt geändert:

     

Wenn Arrays variabler Länge nicht Teil des Standards sind, warum hat GCC das implementiert?

VLAs sind Teil von ISO C99 (gcc und g ++ (als Erweiterung) unterstützen VLAs). MSVC unterstützt immer noch nur C89.

  

Es wird erwartet, dass mein Code auf GCC und MSVC kompiliert wird.

Dann sollten Sie keine VLAs in Ihrem Code IMHO verwenden.

    
Prasoon Saurav 07.07.2010, 08:30
quelle
7
  1. Ja, ist es. Dort gibt es keine spezifischen Verstöße gegen den Standard. Das memset ist zwar Zeitverschwendung, da es sowieso überschrieben wird (mach dein erstes strcat zu einem strcpy ). Und Sie sollten immer überprüfen, ob malloc NULL zurückgibt. Egal was!
  2. C89 / 90 ist nicht der aktuelle Standard, C99 ist. Und C1x ist nicht so weit weg. GCC ist auf dem neuesten Stand.
  3. Verwenden Sie nur lokale Arrays, wenn Sie sie nicht benötigen, um über das Ende der Funktion hinaus zu überleben. Andernfalls ist malloc die beste Wahl, insbesondere wenn Sie die kombinierte Zeichenkette zurückgeben möchten.
  4. Ich denke, gcc hat die -std=c89 -Flagge oder etwas ähnliches. In jedem Fall folgt MSVC nicht immer dem Standard: -)
  5. Kompilieren und testen Sie es häufig auf beiden Plattformen. Das ist der einzige Weg, um sicher zu sein.

Ich würde mich für Folgendes entscheiden:

%Vor%

oder, da Sie nichts mit der Zeichenkette tun, außer sie auszudrucken:

%Vor%

: -)

Eine andere Strategie, die ich gesehen habe, ist die Strategie "nur allokieren, wenn du musst":

%Vor%

verwendet den Stapelspeicher, wenn die kombinierte Zeichenfolge passt und weist nur dann Speicher zu, wenn dies nicht der Fall ist. Dies kann oft zu einer wesentlichen Verbesserung der Geschwindigkeit führen, wenn der Großteil der Strings weniger als die Grenze erreicht.

    
paxdiablo 07.07.2010 08:33
quelle
3

Arrays mit variabler Länge waren nicht Teil des ersten ISO-C-Standards (verschiedentlich als "C89", "C90" oder "ANSI C" bezeichnet). Sie sind jedoch Teil des neuesten ISO-C-Standards (bekannt als "C99").

GCC kann Ihren Code in verschiedenen Modi kompilieren, einschließlich "strict C90", "C90-mit-GNU-C-Extensions" und "C99" (obwohl es nicht vollständig implementiert C99, es ist nah genug für die meisten praktischen Zwecke).

GCC verwendet standardmäßig "C90-mit-GNU-C-Erweiterungen", weshalb Ihr Code ohne Beanstandungen kompiliert wird. Mit -pedantic wird angegeben, dass alle erforderlichen Warnungen vom relevanten Standard (in diesem Fall C90) ausgegeben werden sollen. Eine solche Warnung wird von Ihrem Code benötigt. Wenn Sie GCC die -std=c99 -pedantic -Flags geben, um sie gegen den C99-Basis-Standard zu kompilieren und alle erforderlichen Warnungen zu senden, wird Ihr Code korrekt kompiliert.

Wenn Sie sicherstellen möchten, dass Ihr Code mit dem Basis-C90-Standard kompatibel ist, verwenden Sie -std=c90 -pedantic (oder -ansi -pedantic : -ansi ist ein Synonym für -std=c90 beim Kompilieren von C-Code). Beachten Sie, dass MSVC C99 nicht unterstützt.

    
caf 07.07.2010 08:32
quelle
0

Ein sehr gebräuchliches Idiom, um diese Probleme zu umgehen, ist es, den Anrufer den Speicher verwalten zu lassen. Anstatt also Speicher selbst zuzuordnen (entweder mit einem Array variabler Länge auf dem Stack oder mit malloc oder etwas), erwarten Sie, dass der Aufrufer Speicher bereitstellt. Bedenken Sie Folgendes:

%Vor%

Der Vorteil dieses Ansatzes ist, dass foo niemals leckt. Darüber hinaus kann der Aufrufer ein einfaches Stack-basiertes Array verwenden, falls es für ihn funktioniert. Wenn er die genaue Größe wissen möchte, kann er foo aufrufen und NULL als viertes Argument übergeben.

    
Frerich Raabe 07.07.2010 09:20
quelle

Tags und Links