Die Adresse des Arrays vom Typ char * [2] kann nicht übergeben werden, um die Funktion char zu übernehmen ***

7

Mein XCode (Standardcompiler sollte klingeln?) zeigt mir in diesem Code eine Warnung:

Incompatible pointer types passing 'char *(*)[2]' to parameter of type 'char ***' (beim Aufruf von func)

%Vor%

Dieser Code ist kein Problem (= keine Warnung):

%Vor%

Dies entfernt die Warnung

%Vor%

Ich weiß immer noch nicht, warum der erste eine Warnung ausgibt, während der zweite nicht.

Wenn das erste ein Problem ist, würde ich auch erwarten, dass der erste eine Warnung wie folgt ausgibt:

Incompatible pointer types passing 'char *[2]' to parameter of type 'char **'

    
bwoebi 06.09.2013, 16:40
quelle

4 Antworten

10

Zeit für eine kurze Auffrischung der Array-Semantik.

Außer wenn es der Operand der Operatoren sizeof oder unary & ist oder ein String-Literal verwendet wird, um ein anderes Array in einer Deklaration zu initialisieren, ein Ausdruck vom Typ "N-Element-Array von T " wird in einen Ausdruck vom Typ "pointer to T " konvertiert ("decay"), und der Wert des Ausdrucks wird die Adresse des ersten Elements im Array sein.

Der Ausdruck array in Ihrem Code hat den Typ "2-Elemente-Array von char * " oder char *[2] . Wenn Sie es als Argument an func übergeben, wie in

%Vor%

Der Ausdruck wird in einen Ausdruck vom Typ "pointer to char * " oder char ** konvertiert, was der Typ ist, den Ihre Funktion erwartet, und der Wert des Ausdrucks ist die Adresse des ersten Elements: array == &array[0] . Aus diesem Grund erhalten Sie keine Warnung für das zweite Code-Snippet.

Im ersten Ausschnitt ist das Array ein Operand des unären & -Operators, so dass die Umwandlung in einen Zeigertyp nicht stattfindet; Stattdessen ist der Typ des Ausdrucks "Zeiger auf 2-Element-Array von char * " oder char *(*)[2] , was nicht mit char ** kompatibel ist. Die Adresse value ist dieselbe (die Adresse des ersten Elements des Arrays ist mit der Adresse des Arrays identisch), aber die Typen stimmen nicht überein, daher die Warnung.

Also, warum ist das wichtig? Ein Zeiger ist nur eine Adresse, und alle Adressen sind gleich, oder? Nun, nein. Ein Zeiger ist eine -Abstraktion einer Adresse mit zugehöriger Typ-Semantik. Zeiger auf verschiedene Typen müssen nicht dieselbe Größe oder Darstellung haben, und die Zeigerarithmetik hängt vom Typ des angegebenen Typs ab.

Wenn ich z. B. einen Zeiger als char **p; deklariere, wird der Ausdruck p++ den Zeiger auf das nächste Objekt vom Typ char * oder sizeof (char *) bytes von der aktuellen Adresse weiterleiten. Wenn p jedoch als char *(*p)[2] deklariert ist, wird der Ausdruck p++ auf p vorrücken, um auf das nächste zweielementige Array von char * zu zeigen, was 2 *% co_de ist % Bytes von der aktuellen Adresse.

    
John Bode 06.09.2013, 17:18
quelle
5
%Vor%

ist ein Array mit 2 Elementen von char * .

Die Verwendung von array als Adresse führt zu einem Zeiger auf das erste Element, d. e. vom Typ char ** .

Die Verwendung von &array führt zu einem Zeiger auf dieselbe Stelle, aber vom Typ char *(*)[2] (nicht sicher, ob die Schreibweise richtig ist).

Dies ist nicht dasselbe wie char *** - die Darstellung im Speicher ist komplett anders.

Um ausführlicher zu sein,

%Vor%

Dies ist das Array.

%Vor%     
glglgl 06.09.2013 16:50
quelle
3

Hier ist ein Beispiel, wie Sie tun können, was Sie wollen und ändern Sie, welches Array zeigt auf:

%Vor%     
dcaswell 06.09.2013 17:09
quelle
2

Sie haben ein Array vom Typ char *[2] , d. h. ein Array von 2 Zeigern an char . Es ist ein Array fester Größe mit automatischer Speicherdauer. Das einzige, was Ihre Funktion mit dieser Art von Array tun kann, ist, entweder ihre Elemente zu verwenden oder sie zu ändern (sie kann ihre Größe nicht ändern oder sie nicht freigeben). Daher macht es keinen Sinn zu versuchen, das Array zu ändern selbst ~ & gt; mit anderen Worten: Sie brauchen nicht wirklich einen Zeiger auf diese Art von Array).

Hier ist ein einfaches Beispiel:

%Vor%

oder alternativ func ändern, um ein Array unspezifizierter Größe zu verwenden, das mit char *[X] für jede X verwendbar ist, nicht nur mit 2 (in diesem Fall ist es sinnvoll, die Array-Größe zu übergeben):

%Vor%

mit diesem oder jenem Programm würde dieses Programm value -> new value ausgeben.

Wenn Sie Ihre Funktion benötigen, um die Größe dieses Arrays zu ändern oder das Array selbst auf andere Weise zu beeinflussen, sollten Sie das dynamisch zugewiesene Array und die Übergabe in Form von char** .     

LihO 06.09.2013 17:39
quelle