2013-12-08 4 views
6

C++ 11-Code:C & C++: Was ist der Unterschied zwischen Zeiger-zu-Adresse-Array?

int a[3]; 
auto b = a;  // b is of type int* 
auto c = &a;  // c is of type int(*)[1] 

C-Code:

int a[3]; 
int *b = a; 
int (*c)[3] = &a; 

Die Werte von b und c sind gleich.

Was ist der Unterschied zwischen b und c? Warum sind sie nicht der gleiche Typ?

UPDATE: änderte ich die Array-Größe von 1 bis 3

+0

'auto' spielt nicht gut mit Zeigern, es ist in der Regel nicht vertrauenswürdig mit dieser Art von Typen. – user2485710

+1

@ user2485710 Können Sie das näher ausführen? Irgendwelche Referenzen/Zitate? – Domi

+0

'Auto' funktioniert gut mit Zeigern, keine Ahnung, wo Sie diese Idee haben. –

Antwort

7

Den sizeof Operator anders verhalten sollte, für einen, vor allem wenn Sie die Deklaration von a zu einer unterschiedlichen Anzahl von ganzen Zahlen, wie int a[7] ändern :

int main() 
{ 
    int a[7]; 

    auto b = a; 
    auto c = &a; 

    std::cout << sizeof(*b) << std::endl; // outputs sizeof(int) 
    std::cout << sizeof(*c) << std::endl; // outputs sizeof(int[7]) 

    return 0; 
} 

Für mich ist diese Drucke:

4 
28 

Das liegt daran, dass die beiden Zeiger sehr unterschiedliche Typen sind. Einer ist ein Zeiger auf Ganzzahl und der andere ist ein Zeiger auf ein Array von 7 ganzen Zahlen.

Die zweite hat wirklich Zeiger-zu-Array-Typ. Wenn Sie es dereferenzieren, sicher, es wird decay to a pointer in den meisten Fällen, aber es ist nicht wirklich ein Zeiger auf Zeiger zu int. Der erste ist pointer-to-int, weil der Zerfall bei der Zuweisung passiert ist.

Andere Orte es zeigen würde, bis, wenn Sie wirklich zwei Variablen vom Typ Zeiger-to-Array haben, und versuchten, einen zum anderen zuzuweisen:

int main() 
{ 
    int a[7]; 
    int b[9]; 

    auto aa = &a; 
    auto bb = &b; 

    aa = bb; 

    return 0; 
} 

Dies verdient mir die Fehlermeldung:

xx.cpp: In function ‘int main()’: 
xx.cpp:14:8: error: cannot convert ‘int (*)[9]’ to ‘int (*)[7]’ in assignment 
    aa = bb; 

Dieses Beispiel funktioniert jedoch, weil dereferencing bb es erlaubt zu-int-Zeiger-abklingen:

int main() 
{ 
    int a; 
    int b[9]; 

    auto aa = &a; 
    auto bb = &b; 

    aa = *bb; 

    return 0; 
} 

Beachten Sie, dass der Verfall auf der linken Seite einer Zuweisung nicht auftritt. Dies funktioniert nicht:

int main() 
{ 
    int a[7]; 
    int b[9]; 

    auto aa = &a; 
    auto bb = &b; 

    *aa = *bb; 

    return 0; 
} 

Es bringt Ihnen dies:

xx2.cpp: In function ‘int main()’: 
xx2.cpp:14:9: error: incompatible types in assignment of ‘int [9]’ to ‘int [7]’ 
    *aa = *bb; 
+0

'sizeof' verwirft auch den' const' Teil für Ihren zweiten 'cout' mit dem' c' Variable. Deshalb ergeben sie identische Ausgabe. – user2485710

+0

@ user2485710: Was führt zu identischer Ausgabe? Meine zwei "cout" Zeilen geben zwei verschiedene Zahlen aus. "const" kommt überhaupt nicht ins Bild. Ich bin nicht in der Lage, Ihren Kommentar mit irgendetwas in meinem Beitrag in Einklang zu bringen. –

+0

Große Antwort. Hebt eine ganze Reihe von Konzepten hervor, an die ich vorher nicht viel gedacht habe! Ich sollte wahrscheinlich häufiger Array-Typen zugunsten von Pointer-Typen verwenden! – Domi

6

Die Identität eines Objekts in C++ durch die Paar bestimmt wird seiner Typ und seine Adresse.

In Ihrem Beispiel gibt es zwei verschiedene Objekte mit der gleichen Adresse: Das Array selbst und das erste Element des Arrays. Die erste hat den Typ int[1], die zweite hat den Typ int. Zwei unterschiedliche Objekte können die gleiche Adresse haben, wenn eines ein Teilobjekt des anderen ist, wie dies bei Array-Elementen, Klassenmembern und Klassenbasis-Subobjekten der Fall ist.

Ihr Beispiel wäre klarer, wenn Sie schrieb:

int a[5]; 
int (*ptr_to_array)[5] = &a; 
int * ptr_to_array_element = &a[0]; 

Aber Sie haben sich die Tatsache zunutze gemacht, dass die ID-expression a für das Array zu einem Zeiger zerfällt auf das erste Element des Arrays, so a hat der gleiche Wert wie &a[0] in Ihrem Kontext.

+0

Thanks! Ich habe eine leicht modifizierte Version Ihres Codes zu meiner Frage hinzugefügt. – Domi

1

Betrachten Sie dieses Beispiel:

#include<stdio.h> 

int main() 
{ 
    int myArray[10][10][10][10]; //A 4 Dimentional array; 

    //THESE WILL ALL PRINT THE SAME VALUE 
    printf("%d, %d, %d, %d, %d\n", 
      myArray, 
      myArray[0], 
      myArray[0][0], 
      myArray[0][0][0], 
      &myArray[0][0][0][0] 
     ); 

    //NOW SEE WHAT VALUES YOU GET AFTER ADDING 1 TO EACH OF THESE POINTERS 
    printf("%d, %d, %d, %d, %d\n", 
      myArray+1, 
      myArray[0]+1, 
      myArray[0][0]+1, 
      myArray[0][0][0]+1, 
      &myArray[0][0][0][0]+1 
     ); 
} 

Sie werden feststellen, dass alle 5 in ersten Fall gedruckten Werte alle gleich sind. Weil sie auf den gleichen Ausgangsort zeigen.

Aber nur, wenn Sie sie um 1 erhöhen, sehen Sie, dass verschiedene Zeiger jetzt zu verschiedenen Orten springen (zeigen). Dies liegt daran, dass myArray[0][0][0] + 1 um 10 ganzzahlige Werte, die 40 Bytes sind, springt, während myArray[0][0] + 1 um 100 ganzzahlige Werte, d. H. Um 400 Bytes, springt. Ähnlich springt myArray[0] + 1 um 1000 ganzzahlige Werte oder 4000 Bytes.

Also die Werte hängen davon ab, was Pegel des Zeigers Sie beziehen sich auf.

Aber jetzt, wenn ich Zeiger verwenden, um alle von ihnen zu beziehen:

#include<stdio.h> 

int main() 
{ 
    int myArray[10][10][10][10]; //A 4 Dimentional array; 

      int * ptr1 = myArray[10][10][10]; 
      int ** ptr2 = myArray[10][10]; 
      int *** ptr3 = myArray[10]; 
      int **** ptr4 = myArray; 

    //THESE WILL ALL PRINT THE SAME VALUE 
    printf("%u, %u, %u, %u\n", ptr1, ptr2, ptr3, ptr4); 

    //THESE ALSO PRINT SAME VALUES!! 
    printf("%d, %d, %d, %d\n",ptr1+1,ptr2+1,ptr3+1,ptr4+1); 
} 

Sie sehen also, verschiedene Ebenen von Zeigervariablen verhalten sich nicht so, wie die Array-Variable tut.

Verwandte Themen