2013-12-08 12 views
6

C++ 11:C & C++: Qual è la differenza tra pointer-to e address-of array? codice

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

codice C:

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

I valori di b e c sono gli stessi.

Qual è la differenza tra b e c? Perché non sono dello stesso tipo?

UPDATE: ho cambiato la dimensione della matrice da 1 a 3.

+0

'auto' non funziona correttamente con i puntatori, in genere non è affidabile con questo tipo di tipi. – user2485710

+1

@ user2485710 Puoi approfondire questo? Eventuali riferimenti/citazioni? – Domi

+0

'auto' funziona perfettamente con i puntatori, nessun indizio su dove hai preso l'idea. –

risposta

7

L'operatore sizeof dovrebbe comportarsi in modo diverso, per uno, soprattutto se si modifica la dichiarazione di a ad un numero diverso di numeri interi, come ad esempio int a[7] :

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; 
} 

Per me, questo stampa:

4 
28 

Questo perché i due puntatori sono tipi molto diversi. Uno è un puntatore a numero intero e l'altro è un puntatore a un array di 7 numeri interi.

Il secondo ha effettivamente il tipo puntatore-array. Se lo si dereferenzia, nella maggior parte dei casi sarà decay to a pointer, ma in realtà non è un puntatore a puntatore a int. Il primo è pointer-to-int perché il decadimento è avvenuto durante l'assegnazione.

Altri luoghi rivelerebbe è se davvero avuto due variabili di tipo puntatore-a-array, e ha cercato di assegnare l'uno all'altro:

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

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

    aa = bb; 

    return 0; 
} 

Questo mi fa guadagnare il messaggio di errore:

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

questo esempio, tuttavia, funziona, perché dereferenziare bb permette di decadimento di puntatore a int:

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

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

    aa = *bb; 

    return 0; 
} 

Si noti che il decadimento non avviene sul lato sinistro di un compito. Questo non funziona:

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

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

    *aa = *bb; 

    return 0; 
} 

E si guadagna questo:

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' scartando anche la parte' const' per il tuo secondo 'cout' con' c' variabile. Ecco perché producono risultati identici. – user2485710

+0

@ user2485710: che risultati hanno un output identico? Le mie due linee 'cout' generano due numeri diversi. 'const' non entra affatto nell'immagine. Non sono in grado di allineare il tuo commento con qualcosa nel mio post. –

+0

Ottima risposta. Sottolinea un sacco di concetti a cui non ho pensato molto, in precedenza! Probabilmente dovrei usare più spesso i tipi di array a favore dei tipi di puntatore! – Domi

6

L'identità di qualsiasi oggetto in C++ è determinata dal due del suo tipo e la sua indirizzo.

Ci sono due oggetti distinti con lo stesso indirizzo nell'esempio: la matrice stessa e il primo elemento della matrice. Il primo ha il tipo int[1], il secondo ha il tipo int. Due oggetti distinti possono avere lo stesso indirizzo se uno è un suboggetti dell'altra, come nel caso degli elementi di array, membri della classe e sottooggetti di base della classe.

Il tuo esempio sarebbe più chiaro se hai scritto:

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

Ma voi hanno approfittato del fatto che l'id-espressione a per la matrice decade in un puntatore al primo elemento dell'array, così a ha lo stesso valore di &a[0] nel tuo contesto.

+0

Grazie! Ho aggiunto una versione leggermente modificata del tuo codice alla mia domanda. – Domi

1

Considerate questo esempio:

#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 
     ); 
} 

Troverete che tutti i 5 valori stampati in primo caso sono tutti uguali. Perché indicano la stessa posizione iniziale.

Ma proprio quando si incrementano di 1 si vede che i diversi puntatori ora saltano (punto) in posizioni diverse. Questo perché myArray[0][0][0] + 1 salterà di 10 valori interi di 40 byte, mentre myArray[0][0] + 1 salterà di 100 valori interi, vale a dire 400 byte. Allo stesso modo myArray[0] + 1 salta di 1000 valori interi o 4000 byte.

Così i valori dipendono ciò livello di puntatore si fa riferimento.

Ma ora, se io uso i puntatori per indicare tutti loro:

#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); 
} 

Quindi, vedete, i diversi livelli di variabili puntatore non si comportano il modo in cui la variabile di matrice fa.

Problemi correlati