2016-04-15 10 views
2

Ich weiß, dass bei Verwendung als Funktion Parameter char* a[] entspricht char a[][] entspricht. Mit char * a [] vs char a [] []

Bei Verwendung als Funktionsparameter entspricht char* a[]char** a. Also known as Array to pointer conversion to some.

jedoch, wenn in Block Umfang verwendet sie sind nicht die gleichen, und ich bin verwirrt, wenn ich einen über den anderen vorziehen sollte, oder wenn ich char a[][] überspringen sollte, wie ich in der Regel dazu neigen, char* a[] in anderen zu sehen Menschen Code.

Ein Argument gegen char a[][] ist offensichtlich, dass Sie eine feste Größe für die C-Strings geben müssen, die es enthalten wird, aber beeinflusst das die Leistung in irgendeiner Weise?

Sollte ich es vorziehen, diese:

char* a[] = {"hello", "world"}; 

Oder diese:

char a[][10] = {"hello", "world"}; 
+1

Vorsicht vor jedem Satz, der mit "Ich weiß das" beginnt ... –

+0

@KerrekSB Was meinst du? – hgiesel

+4

Ihre führende Behauptung ist falsch. 'char a [] []' ist niemals erlaubt. Was als Funktionsparameter types äquivalent ist, ist char * a [] 'und' char ** a'. –

Antwort

2

Die Anpassung des Array-Typs an den Zeigertyp funktioniert nur, wenn er als Parameter einer Funktion deklariert ist.
Als Funktionsparameter wird char* a[] auf char** a und char a[][10] auf char (*a)[10] eingestellt. Ansonsten char* a[] deklariert a als ein Array von Zeigern zu char während char a[][10] erklärt a ein Array von Arrays von char.

Preference von

char* a[] = {"hello", "world"}; 

über dieses

char a[][10] = {"hello", "world"}; 

Sinn machen, wenn Sie einige Bytes Speicher gespeichert werden soll. In letzterem Fall werden für jeden von a[0] und a[1] 10 Bytes vergeben. Beachten Sie, dass im Fall von char* a[] Strings, auf die Elemente von a zeigen, unveränderlich sind.

Wenn Sie eine zusammenhängende Speicherzuweisung wünschen, gehen Sie mit char a[][10].

+0

Die OPs Frage unterscheidet sich vom Titel. – Michi

+0

Irgendwie gibt es nichts wirklich zu diskutieren über "Array of Arrays" (oder Multi-Dim) vs "Array of Pointers", die definitiv verschiedene Dinge sind. – Michi

+0

@Michi; Ja. das habe ich in meiner Antwort angesprochen. – haccks

8

Der Schlüssel, um die scheinbar seltsame Syntax Fälle von Funktionsparametern zu verstehen ist Array Verfall zu verstehen. Dies ist alles über eine Regel in C, die besagt, , wenn Sie ein Array als Parameter an eine Funktion übergeben, zerfällt es in einen Zeiger auf das erste Element dieses Arrays (*).

Also, wenn Sie so etwas wie

void func (int a[5]); 

dann zur Compile-Zeit zu schreiben, wird das Array mit einem Zeiger auf das erste Element ersetzt, so dass die oben gleich:

void func (int* a); 

Diese Regel von Pointer Decay gilt rekursiv für mehrdimensionale Arrays. Wenn Sie also ein mehrdimensionales Array an eine Funktion:

void func (int a[5][3]); 

es zerfällt nach wie vor auf einen Zeiger auf das erste Element. Nun ist ein 2D-Array eigentlich ein Array von Arrays. Das erste Element ist daher ein eindimensionales Array mit der Größe 3 in diesem Beispiel. Sie erhalten einen Array-Zeiger zu diesem Array, den Typ int(*)[3]. So machen Sie die äquivalent zu

void func (int (*a)[3]); 

Und das ist eigentlich der Grund, warum wir die am weitesten links stehenden Dimension der Array-Parameter, und nur diese Dimension weglassen. Auf diese Weise machen wir ein Array von unvollständigen Typen, die Sie normalerweise nicht verwenden könnten: Sie können beispielsweise keinen Code wie int array[]; in den Körper einer Funktion schreiben. Aber im Parameterfall spielt es keine Rolle, dass die äußerste linke Dimension nicht angegeben wird, da diese Dimension sowieso "abfällt".


(*) Quelle, C11 6.7.6.3/7:

Eine Erklärung eines Parameters als '' Array vom Typ '' ist auf '' qualifizierte Zeiger auf Typ‘eingestellt werden, ', ...

+3

gegeben Ist das nicht * Argumente *, die verfallen? Ich bin mir ziemlich sicher, dass die Parameter typisiert sind. – juanchopanza

+1

@juanchopanza Umm ... Argument und Parameter sind Synonyme? – Lundin

+0

Die Aussage über unvollständige Typen ist ein wenig vage. Es gibt * Verwendungen für unvollständige Typen, z.B. Sie können sie in Deklarationen verwenden: Zum Beispiel ist 'extern int a [];' in einer Funktion in Ordnung. –