18 Stimmen

C: Wie deklariert man korrekt ein Array von Strings?

Ich habe beides gesehen:

const char*  arr = {"foo", "bar"};

et

const char*  arr[] = {"foo", "bar"};

Was ist der richtige und allgemein übliche Weg?

Was ist der Unterschied zwischen zwei?

Was ist der Unterschied zwischen

   const char**arr = {"foo", "bar"};

et

    const char* arr[] = {"foo", "bar"};

et

   const char* * const arr = {"foo", "bar"};    

et

   const char* const * const arr = {"foo", "bar"};

Entschuldigung für die vielen Fragen, ich versuche nur, es besser zu verstehen...

24voto

CB Bailey Punkte 693084

Dies ist nicht korrekt, da es nicht die richtige Ebene der Indirektion hat.

const char* arr = {"foo", "bar"};

Das ist nicht korrekt, denn es fehlt ein = . Es sieht ein bisschen aus wie eine Funktionsdefinition.

const char* arr[] {"foo", "bar"};

Dies ist die übliche korrekte Form.

const char* arr[] = { "foo", "bar" };

bearbeiten

Sie können einen Zeiger nicht über einen Aggregat-Initialisierer initialisieren (d. h. { ..., ..., ... } ). Sie können beides tun

const char* str1 = "A string";

et

const char str2[] = "Another string";

aber das hier ist anders.

Ein String-Literal hat den Typ 'array of n char' und kann daher in einen Zeiger umgewandelt werden, während eine Initialisierungsliste nicht wirklich ein Array ist, sondern nur eine Möglichkeit, Arrays zu initialisieren.

12voto

Bill Hoag Punkte 537

In Bezug auf die Konstante...

const char* constValue = "foo";
constValue = "bar";
constValue[0] = 'x'; // will not work

char* const constPtr = "foo";
constPtr = "bar"; // will not work
constPtr[0] = 'x';

const char* const arr[] = { "foo", "bar", 0 }; // all const

'const char* const' ist oft die beste Lösung für etwas völlig Konstantes. Eine weitere Optimierung bestünde darin, diesen Wert auch statisch zu machen, wenn er in einem lokalen Bereich deklariert wird. Der 0 ptr ist nützlich für einen Sentinel-Wert.

1voto

John Bode Punkte 112486

Es gibt mehrere Ansätze. Der einfachste ist, ein Array von Arrays of Char zu deklarieren, etwa so:

char strs[N][M + 1]; // M is max length of each string
...
strcpy(strs[i], "foo");

Der gesamte Speicher für die Zeichenketten wird statisch zugewiesen, aber die Größe jeder Zeichenkette im Array ist festgelegt, und Sie müssen die Größe für die längste mögliche Zeichenkette festlegen, was zu einer gewissen internen Fragmentierung führen kann. Alle Zeichenketten sind beschreibbar.

Ein anderer Ansatz besteht darin, ein Array von Zeigern auf char zu deklarieren:

char *strs[N];
...
strs[i] = malloc(strlen("bar") + 1);
if (strs[i]) 
  strcpy(strs[i], "bar"); 

Auf diese Weise können Sie so viel oder so wenig Speicher zuweisen, wie jeder String im Array benötigt, und Sie können die Größe Ihrer Strings bei Bedarf ändern. Sie können auch einfach auf String-Literale verweisen, aber denken Sie daran, dass Literale möglicherweise nicht beschreibbar sind, d.h. Sie können möglicherweise nicht so etwas tun wie:

strs[j] = "foo";
strs[j][0] = 'b'; // may not be allowed on string literal

Sie können den gesamten Smash dynamisch zuweisen:

char **strs = malloc(sizeof *strs * N);
for (i = 0; i < N; i++)
  strs[i] = malloc(SIZE + 1);

Auf diese Weise können Sie nicht nur die Größe jeder einzelnen Zeichenkette nach Bedarf ändern, sondern auch die Anzahl der Zeichenketten. Beachten Sie, dass in diesem Fall strs pas ein Array-Typ, auch wenn es als Array behandelt wird.

Beachten Sie, dass sich die besten Praktiken in Bezug auf malloc() zwischen C und C++ unterscheiden. In C gilt es als schlechte Praxis, das Ergebnis von malloc() zu casten. Zum einen ist es unnötig, da void-Zeiger implizit auf andere Objektzeigertypen gecastet werden. Zum anderen wird dadurch eine Diagnose unterdrückt, wenn man vergisst, stdlib.h zu inkludieren oder keinen Prototyp für malloc() im Gültigkeitsbereich hat. Denken Sie daran, dass C, wenn es keinen Prototyp für eine Funktion sieht, bevor sie referenziert wird, annimmt, dass die Funktion int zurückgibt, was nicht implizit in einen Zeigertyp umgewandelt werden kann.

-2voto

Paul Nathan Punkte 38618

Normalerweise verwende ich hier, wenn möglich, dynamischen Speicher. Ich finde, es ist einfacher, über Zeiger nachzudenken, als mit dem Array-Typ zu kämpfen.

//Allocate pointers for the strings
char **c = (char**)malloc(maxnumofstrs*sizeof(int));
//allocate memory for each string
for(int i = 0; i < maxnumofstrs; i++)
{
   c[i] = (char*)malloc(maxwidth);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X