2013-07-02 12 views
50

Sto imparando il linguaggio di programmazione C, ho appena iniziato a imparare gli array con i puntatori. Ho un problema in questa domanda, spero che quell'uscita debba essere 5 ma è 2, Qualcuno può spiegare perché?Il mio puntatore char indica un valore non valido dopo il cast da int *

int main(){ 
    int arr[] = {1, 2, 3, 4, 5}; 
    char *ptr = (char *) arr; 
    printf("%d", *(ptr+4)); 
    return 0; 
} 
+12

Se qualcuno vota questa domanda, per favore menziona il tuo commento, è molto difficile per me, speriamo non per gli altri .... :) –

+12

Hai un " int "array, ma un puntatore" char ". – Lucas

+6

+1 sul tuo annuncio :) –

risposta

79

Assumiamo un'architettura little endian in cui un int è 32 bit (4 byte), i singoli byte di int arr[] appaiono come questo (byte meno significativo nell'indirizzo inferiore).Tutti i valori in esadecimale):

|01 00 00 00|02 00 00 00|03 00 00 00|04 00 00 00|05 00 00 00 
char *ptr = (char *) arr; 

Ora, ptr punta al primo byte - da quando si è fusa per char*, viene trattato come array di caratteri in poi:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0 
^ 
+-- ptr 

Quindi, *(ptr+4) accede al quinto elemento dell'array char e restituisce il valore char corrispondente:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0 
     ^
     +-- *(ptr + 4) = 2 

Quindi, printf() stampe 2.

In un sistema Big Endian, l'ordine dei byte all'interno di ogni int è invertita, con conseguente

|0|0|0|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5 
     ^
     +-- *(ptr + 4) = 0 
+4

grazie signore, la vostra risposta mi dà la migliore rappresentazione visiva, .... :) –

+3

Mescolate la vostra endianess, little endian ha il minimo nella posizione di memoria più bassa. –

+3

La descrizione di come 'printf()' gestisce questo caso non è corretta. Sta ottenendo il valore del quinto carattere come un intero, non un puntatore allo stesso. Inoltre, come dice Joachim, la tua endianità è capovolta. – Hasturkun

13

E 'perché la dimensione di char è uno, e la dimensione del int è quattro. Ciò significa che l'aggiunta di 4 a ptr rende il risultato puntato alla seconda voce nell'array int.

Se lo hai compilato su un grande sistema endian, avresti invece stampato 33554432.

+1

Ho pensato che endian si applicava solo a virgola mobile. Stai suggerendo che gli interi si comportino allo stesso modo? Non sono così sicuro. – Bathsheba

+5

Ovunque esista un tipo che utilizza più di 1 byte, c'è una domanda su quale ordine memorizzare i byte. – Joe

+9

@Bathsheba Endianess è * sicuramente * un problema di numero intero. –

3
int main(){ 
int arr[] = {1,2,3,4,5}; 
char *ptr = (char *) arr; 
printf("%d",*(ptr+4)); 
return 0; 
} 

Ogni caso di arr ha sizeof(int) dimensioni (che può essere 4 sul tuo implementazione).

Da ptr è un puntatore a char, pointer arithmetic rende ptr + 4 punti 4 byte dopo &arr[0], che può essere &arr[1].

In memoria, sembra che qualcosa di simile a:

Address | 0 1 2 3 | 4 5 6 7 | ... 
Value | arr[0] | arr[1] | ... 
+0

grazie signore per questo aiuto visivo ... –

2

Su una piattaforma a 32 bit, int è quattro volte più grande del char. Quando aggiungi 4 a ptr, aggiungi 4 volte la dimensione di ciò che ptr punta a in ptr (che di per sé è una posizione di memoria). Questo è l'indirizzo del secondo elemento nell'array int.

Su una piattaforma a 64 bit, è intotto volte la dimensione di char; e il tuo risultato sarebbe molto diverso.

Per farla breve, il tuo codice non è portatile (vedi anche la risposta di Joachim Pileborg) ma divertente da disfare.

+1

La dimensione di memorizzazione 'int' dipende dall'implementazione. Sulla maggior parte delle piattaforme a 64 bit, 'sizeof (int)' è 4. Vedi http://stackoverflow.com/questions/384502/what-is-the-bit-size-of-long-on-64-bit-windows per più informazioni –

2

Quello che fai non è assolutamente raccomandato nel codice di produzione, ma è sicuramente ottimo per capire i puntatori, i cast, ecc. Nel processo di apprendimento, quindi per questo il tuo esempio è ottimo. Quindi, perché ottieni 2. È perché il tuo array è una matrice di ints, che a seconda dell'architettura ha dimensioni diverse (nel tuo caso, sizeof(int) è 4). Si definisce ptr come un puntatore char, il char ha dimensione 1 byte. L'aritmetica puntatore (è quello che fai quando scrivi ptr+4) funziona con la dimensione degli oggetti a cui fa riferimento il puntatore, nel tuo caso con i caratteri. Pertanto, ptr+4 è a 4 byte di distanza dall'inizio dell'array e quindi nella seconda posizione dell'array int. È così. Prova ptr+5, dovresti ottenere 0.

1

Poiché state coverting int * a char * ptr [0] = 1, ptr [4] = 2, ptr [8] = 3, ptr [12] = 4, ptr [16] = 5 e tutti gli altri uguali a 0. ptr + 4 punti al quarto elemento nell'array ptr. Così risultato è 2.

+0

@Joe Ho provato il codice, è corretto. – dijkstra

+0

che dipende dalla endianness del tuo sistema. Non hai spiegato perché funziona così e perché è corretto sulla tua macchina. – Joe

1
int main(){ 
int arr[] = {1,2,3,4,5}; 
char *ptr = (char *) arr; 
printf("%d",*(ptr+4)); 
return 0; 
} 

Immaginate arr è memorizzato all'indirizzo 100 (indirizzo totalmente muto). In modo da avere: arr[0] viene memorizzato l'indirizzo 100. arr[1] viene memorizzato l'indirizzo 104. (c'è è 4 a causa del tipo int) arr[2] viene memorizzato l'indirizzo 108. arr[3] viene memorizzato all'indirizzo 112 Ecc.

Ora si sta facendo char *ptr = (char *) arr;, quindi ptr = 100 (lo stesso di arr). La prossima affermazione è interessante, specialmente il secondo argomento di printf: *(ptr+4). Ricorda che ptr = 100. Quindi ptr + 4 = 104, lo stesso indirizzo che arr[1]! Quindi stamperà il valore di , che è 2.

Problemi correlati