Unterschied zwischen 'a' und '& a' in C ++, wobei 'a' ein Array ist

8

Ich bin verwirrt über die Ausgabe des folgenden Codes.

%Vor%

Die Ausgabe ist

%Vor%

Wie können a und &a denselben Ausdruck ausgeben, aber unterschiedliche Größen haben? Ich dachte immer, dass für jedes Array sein Name immer den Wert = Adresse des ersten Bytes hat.

Auch &a sollte keinen Sinn ergeben, da man keine Adresse (erhalten mit dem & amp; -Operator) zu einer Adresse (den Wert von a) haben kann. Aber der Code gibt eine Ausgabe und tatsächlich 'a == & amp; a' entsprechend der Ausgabe.

In ähnlicher Weise ist die Ausgabe von sizeof(a) = 12 (das ist der gesamte Speicher belegt) durch das Array? a ist ein "Zeiger" selbst sizeof (a) = 4 Bytes (auf meinem 32-Bit Ubuntu 11.04)

Offensichtlich gibt es einige Missverständnisse, die ich habe. Könnte jemand das für mich klären?

    
curiousexplorer 03.01.2014, 20:42
quelle

3 Antworten

13

Ein Array ist kein Zeiger, aber ein Array zerfällt in einen Zeiger, wenn Sie versuchen, es wie einen zu verwenden. In Ihrem Fall wird die Adresse des Arrays automatisch in einen Zeiger umgewandelt.

Es gibt kaum einen Unterschied zwischen dem automatisch konvertierten Zeiger und dem, der explizit mit & erzeugt wurde, außer dass einer ein Zeiger auf ein einzelnes Element ist, während der andere ein Zeiger auf das gesamte Array ist. Wenn Sie &a[0] verwendet hätten, wären sie identisch.

    
Mark Ransom 03.01.2014 20:45
quelle
7

Stellen Sie zunächst fest, dass es einen Unterschied zwischen einem Objekt 1 und dem Ausdruck gibt, mit dem wir uns auf dieses Objekt beziehen. In Ihrem Code ist a ein Ausdruck, der auf ein Objekt verweist, das groß genug ist, um 3 int -Werte zu speichern.

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 " umgewandelt ("decay"), und der Wert des Ausdrucks wird die Adresse des ersten Elements des Arrays sein.

Gegeben eine Aussage wie

%Vor%

Der Ausdruck a hat den Typ "3-Elemente-Array von int "; Da a kein Operand der Operatoren sizeof oder unary & ist, wird es in einen Ausdruck vom Typ "pointer to int " konvertiert, und der Wert des Ausdrucks ist die Adresse des ersten Element im Array.

OTOH, mit einer Aussage wie

%Vor%

Der Ausdruck a ist der Operand des unären & Operators, daher gilt die Regel nicht; Stattdessen ist der Typ des Ausdrucks "Zeiger auf 3-Elemente-Array von int " und der Wert des Ausdrucks ist die Adresse des Arrays.

Sowohl in C als auch in C ++ sind die Adresse des Arrays und die Adresse des ersten Elements des Arrays identisch, daher liefern beide Ausdrücke denselben Wert , aber die Typen der beiden Ausdrücke sind unterschiedlich ( int * vs. int (*)[3] ).

In der Aussage

%Vor%

Der Ausdruck a ist der Operand des Operators sizeof . Auch hier gilt die Konvertierungsregel nicht; stattdessen wird der Ausdruck sizeof a zu der Anzahl der Bytes ausgewertet, die vom Array verwendet werden (in diesem Fall 12).

In der Aussage

%Vor%

Der Ausdruck &a ergibt die Adresse des Arrays und hat den Typ int (*)[3] , daher berechnet sizeof &a die Anzahl der vom Zeigertyp verwendeten Bytes (in Ihrem Fall 4 Bytes).

In C und C ++, wenn Sie ein Array wie

deklarieren %Vor%

Der einzige Speicherplatz, der reserviert ist, ist für die 3 Array-Elemente; Es gibt keinen separaten Speicher für eine Variable a , die auf das erste Element des Arrays zeigt (deshalb liefern a und &a den gleichen Wert).

1. Im Sinne von etwas, das die Erinnerung beschäftigt, nicht den Sinn einer Instanz einer Klasse
John Bode 03.01.2014 21:32
quelle
1

In C ist der Ausdruck a ein primärer Ausdruck, der ein Array-Objekt bezeichnet. In einem Kontext, in dem dieser Ausdruck ausgewertet wird, erzeugt er einen Wert vom Zeigertyp und zeigt auf das erste Element des Arrays.

Dies ist eine spezielle Bewertungsregel für Arrays. Es bedeutet nicht, dass a ein Zeiger ist. Es ist nicht; a ist ein Array-Objekt.

Wenn die Operatoren sizeof von & auf a angewendet werden, wird sie nicht ausgewertet. sizeof erzeugt die Größe des Arrays und & nimmt seine Adresse: Es erzeugt einen Zeiger auf das Array als Ganzes.

Die Werte der Ausdrücke a und &a zeigen auf denselben Ort, haben jedoch einen anderen Typ: einen Zeiger auf den Typ des Array-Elements (z. B. Zeiger auf int ) im Vergleich zum Typ des Array (z. B. Zeiger auf Array von 10 int).

C ++ funktioniert in diesem Bereich sehr ähnlich für die Kompatibilität mit C.

Es gibt andere Situationen in C, in denen der Wert eines Ausdrucks, der einen Wert oder ein Objekt eines Typs bezeichnet, einen Wert eines anderen Typs erzeugt. Wenn c den Typ char hat, ist der Wert von c ein Wert vom Typ int . Doch &c hat den Typ char * , und sizeof c erzeugt 1. Genau wie ein Array kein Zeiger ist, ist c kein int ; es produziert nur einen.

C ++ ist in diesem Bereich nicht kompatibel; Zeichenausdrücke wie Namen von char Variablen oder Zeichenkonstanten wie 'x' haben den Typ char . Dadurch können void foo(int) und void foo(char) unterschiedliche Überladungen einer Funktion foo sein. foo(3) ruft die erste und foo('x') die zweite auf.

    
Kaz 17.05.2014 13:29
quelle

Tags und Links