web-dev-qa-db-de.com

Wie kann man ein Array mit einem Null-Abschlusszeichen merken?

Was ist der richtige und sicherste Weg, um das gesamte Zeichen-Array mit dem Null-Abschlusszeichen zu speichern? Ich kann ein paar Verwendungen auflisten:

...
char* buffer = new char [ARRAY_LENGTH];

//Option 1:             memset( buffer, '\0', sizeof(buffer) );
//Option 2 before edit: memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );
//Option 2 after edit:  memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );
//Option 3:             memset( buffer, '\0', ARRAY_LENGTH );
...
  • Hat einer von diesen einen signifikanten Vorteil gegenüber anderen?
  • Mit welchen Problemen kann ich mit den Anwendungen 1, 2 oder 3 konfrontiert werden?
  • Wie gehe ich am besten mit dieser Anfrage um?
13
Koray

Die Optionen eins und zwei sind einfach falsch. Der erste verwendet die Größe eines Zeigers anstelle der Größe des Arrays, so dass er wahrscheinlich nicht in das gesamte Array schreibt. Die zweite verwendet sizeof(char*) anstelle von sizeof(char), so dass nach dem Ende des Arrays geschrieben wird. Option 3 ist in Ordnung. Sie könnten dies auch verwenden

memset( buffer, '\0', sizeof(char)*ARRAY_LENGTH );

aber sizeof(char) ist garantiert 1.

18
Dirk Holsopple

Der idiomatische Weg ist die Wertinitialisierung des Arrays:

char* buffer = new char [ARRAY_LENGTH]();

Option 1 setzt nur die ersten sizeof(char*)-Bytes auf 0 oder führt zu undefiniertem Verhalten, wenn ARRAY_LENGHT < sizeof(char*).

Option 2 führt zu undefiniertem Verhalten, weil Sie versuchen, mehr als ARRAY_LENGTH-Bytes zu setzen. sizeof(char*) ist fast sicher größer als 1.

Da dies jedoch C++ ist (keine new in C), empfehle ich, stattdessen einen std::string zu verwenden.

Für C (angenommen malloc anstelle von new[]) können Sie verwenden 

memset( buffer, 0, ARRAY_LENGTH );
13
Luchian Grigore

Da sich die Frage ständig ändert, definiere ich:

1: memset( buffer, '\0', sizeof(buffer) );

2a: memset( buffer, '\0', sizeof(char*) * ARRAY_LENGTH );

2b: memset( buffer, '\0', sizeof(char) * ARRAY_LENGTH );

3: memset( buffer, '\0', ARRAY_LENGTH );

Wenn die Frage lediglich "Wie lautet der richtige Weg, um memset zu rufen" und nicht "Wie ist der beste Weg, um dieses Array auf Null zu setzen", so ist entweder 2b oder 3 richtig. 1 und 2a sind falsch.

Du kannst einen Stilkrieg über 2b vs. 3 haben: Ob nun die sizeof(char) oder nicht - einige Leute lassen es aus, weil es überflüssig ist (was ich normalerweise tue), andere setzen es ein, um eine Art Konsistenz mit derselben Codeeinstellung zu schaffen ein Array von int. Das heißt, sie multiplizieren eine Größe immer mit einer Anzahl von Elementen, obwohl sie wissen, dass die Größe 1 ist. Eine mögliche Schlussfolgerung ist, dass der "sicherste" Weg, das Array, auf das buffer zeigt, Memset ist, ist:

std::memset(buffer, 0, sizeof(*buffer) * ARRAY_LENGTH);

Dieser Code bleibt korrekt, wenn sich der Typ des Puffers ändert, vorausgesetzt natürlich, dass er weiterhin ARRAY_LENGTH-Elemente eines beliebigen Typs enthält, vorausgesetzt, dass alle Bits Null den korrekten Anfangswert aufweisen.

Eine andere beliebte Option von "C++ ist nicht C" -Programmierern ist:

/* never mind how buffer is allocated */
std::fill(buffer, buffer + ARRAY_LENGTH, 0);

Wenn es Ihnen wichtig ist, können Sie selbst prüfen, ob Ihr Compiler dies auf denselben Code optimiert, mit dem der entsprechende Aufruf von std::memset optimiert wird.

char *buffer = new char [ARRAY_LENGTH](); ist in C++ praktisch, aber praktisch unbrauchbar, da Sie mit new eigentlich nie ein Array zuweisen.

std::string buffer(ARRAY_LENGTH, 0); führt eine bestimmte Art der Verwaltung des Puffers ein, die möglicherweise nicht das ist, was Sie möchten, aber häufig auch ist. Für char buffer[ARRAY_LENGTH] = {0}; ist in manchen Fällen viel zu sagen.

5
Steve Jessop
  • Hat einer von diesen einen signifikanten Vorteil gegenüber anderen?
  • Mit welchen Problemen kann ich mit den Anwendungen 1, 2 oder 3 konfrontiert werden?

1st ist falsch, weil sizeof(buffer) == sizeof(char*).

2. und 3. sind in Ordnung.

  • Wie gehe ich am besten mit dieser Anfrage um?

Warum nicht einfach:

buffer[0] = '\0';

Wenn dies ein char-Array ist, warum sollten Sie sich mit den restlichen Zeichen beschäftigen? Wenn das erste Byte auf Null gesetzt ist, haben Sie das Äquivalent von "" in Ihrer buffer.

Wenn Sie wirklich darauf bestehen, buffer auf Null zu setzen, verwenden Sie die Antwort natürlich mit std::fill - dies ist der richtige Weg. Ich meine std::fill(buffer, buffer + ARRAY_LENGTH, 0);.

3
PiotrNycz

Wenn Sie unbedingt ein Raw-Array in C++ verwenden müssen (dies ist eine sehr schlechte Idee), machen Sie es so:

char* buffer = new char [ARRAY_LENGTH]();

Für C++ ist memset in der Regel die letzte Zuflucht des Inkompetenten, obwohl ich in den letzten Monaten gelernt habe, dass für akzeptable Leistung mit den aktuellen Werkzeugen dieses Niveau erreicht werden muss, wenn man seine eigene String-Klasse implementiert.

Verwenden Sie anstelle dieser unformatierten Arrays usw., die memset zu benötigen scheinen, z. std::string (für den obigen Fall), std::vector, std::array usw.

Seit C++ 11 würde ich wählen:

#include <array>

std::array<char, ARRAY_LENGTH> buffer{ '\0' };

buffer.fill('\0');
1
Amit G.

Nun, persönlich mag ich Option 3:

memset( buffer, '\0', ARRAY_LENGTH )

ARRAY_LENGTH ist genau das, was ich in den Speicher füllen möchte.

0
Simon Lau

Option 3: memset( buffer, '\0', ARRAY_LENGTH ): gibt nur die Länge des Arrays an, aber tatsächlich ist dieser Parameter die Gesamtmenge des Speichers in Byte.

Option 1: memset( buffer, '\0', sizeof(buffer) ): gibt Ihnen eine falsche Antwort, da bufferchar* ist. sizeof(buffer) würde Ihnen nicht die Größe eines ganzen Arrays geben, sondern nur die Größe einer Zeigervariable.

Option 2 ist richtig.

0
taufique