2010-10-31 6 views
5

Come da quello che so sull'operatore '&', restituisce l'indirizzo di base dell'operando in memoria.Informazioni sull'operatore '&'

Immaginiamo il seguente scenario (come sulla mia macchina):

  • sizeof (int) = 4 byte
  • sizeof (float) = 4 byte
  • sizeof (char) = 1 byte

Ora, se scrivo qualcosa di simile:

void main() { 
int i = 5411; 
int *ip = &i; 
char *c = &i; 

printf("%d",*ip); 
printf("%c",*c); 
} 

Il primo printf() dovrebbe darmi 5411. Parlando del secondo printf(), l'indirizzo di base di i contiene 10101001 (8 bit di ordine superiore = 1 byte per il puntatore di tipo char). Quindi * c dovrebbe darmi 169, che quando convertito in% c è un carattere non valido.

Ma il compilatore mi sta restituendo '#' o qualche altra uscita valida. Perché è così ? Qualsiasi input?

EDIT (tratto dal commento dell'autore su una delle risposte):

Questo è stato solo un caso fittizio, da quando ero lontano dalla macchina reale.
Il caso reale è i = 5411

+0

In ogni caso, se si tenta di "stampare" un "carattere" verrà visualizzato come un carattere, non come il codice intero corrispondente. –

+0

probabilmente qualcosa a che fare con la codifica dei caratteri in uso, direi. –

+0

Sì, anch'io sono d'accordo. Ma ci deve essere una ragione per ottenere il valore "#" dall'ultimo printf(). Non è un valore spazzatura. –

risposta

24

Sembra che tu abbia difficoltà a capire come gli interi vengono archiviati in memoria. Prendi 5411 come esempio.

5411 = 1010100100011 

questo numero 13 cifre binarie ha tuttavia, poiché un int è 32 bit, deve essere pad a 32 cifre

5411 = 00000000 00000000 00010101 00100011 

Su una macchina little endian (x86, ARM di default), i byte meno significativi sono memorizzati nella parte anteriore, quindi nella memoria:

00100011 00010101 00000000 00000000 
^ 
c   c + 1  c + 2  c + 3 
ip 

Pertanto, *c dovrebbe restituire 00.100.011 esempio 35 ('#').

+0

Hey grazie mille !! Questo è esattamente quello che stavo cercando :-) –

+0

Da dove proviene '5411'? Il codice dell'OP inizializza chiaramente 'i' con' 1154'. – AnT

+0

@AndreyT: vedi i commenti dell'OP su altre risposte. – kennytm

5

ASCII definisce solo i caratteri fino a 127. Oltre a questo, ciò che si vuole veramente fare è stampare il valore numerico corrispondente al valore in *c, questo viene fatto utilizzando anche %d. ..

printf("%d",*c); 

... dovrebbe visualizzare il numero come previsto.

+0

Questo era solo un caso fittizio, poiché ero lontano dalla macchina reale. Il caso reale è i = 5411.% c restituisce '#' e% d restituisce 35 (anziché 169) –

+0

@Guarav: ASCII definisce solo caratteri fino a 127, e ciò che sembra davvero che desideri è stampare numeri, quindi stampa numeri, non caratteri. –

+2

@Gaurav - Perché ti aspetti 169? Su una macchina little endian, dovrebbe essere 35. Su una macchina big endian, dovrebbe essere 0. –

1

L'indirizzo di * c è quello di i, poiché è stata assegnata c a & i. Prenderà quindi il più alto o il più basso (dipende dall'endian) e stamperà quel personaggio.

+0

Il caso di i = 5411 sta stampando '#' come carattere. Un ASCII di 35 (10101001), che non è né l'8 superiore né 8 bit inferiori. –

+0

@Gaurav - 35 in binario è 00100011 –

+0

concordato. Non ci sarà un troncamento con * c perché il puntatore del carattere è abbastanza grande da contenere l'intero valore della posizione di memoria. –

1

solo per imparare qualcosa sulla codifica dei vostri numeri interi si dovrebbe sperimentare un po 'e fare

printf("0x%X, %X|%X|%X|%X\n", 
    i, 
    i & 0xFF, 
    (i >> 8) & 0xFF 
    (i >> 16) & 0xFF 
    (i >> 24) & 0xFF 
); 

An poi fare lo stesso con c[0], c[1] ecc e altre stringhe di formato come %c.

3

In primo luogo, il programma è mal formato. Né C né C++ consentono di inizializzare un puntatore char * con un valore int *. È necessario un cast esplicito nell'inizializzazione del puntatore c.

In secondo luogo, quale byte dell'intero originale i - ordine superiore o inferiore - risiede nel suo "indirizzo di base" è definito dall'implementazione. Esistono architetture little-endian, in cui l'ordine inferiore è visibile tramite *c (che ha il valore 130 su una macchina char a 8 bit, non 114). E ci sono architetture big-endian, dove l'ordine più alto, ma sarà visto attraverso *c (che è 0 su una macchina a 8 bit char). Quindi è necessario aspettarsi un carattere con il codice 130 o un carattere con il codice 0 da stampare con l'identificatore di formato %c.

In terzo luogo, in un'implementazione tipica di solito non esiste un "codice carattere non valido". Per qualsiasi codice, di solito viene stampato in un modo o nell'altro. Non vedo però come sei riuscito a ottenere # come output dal tuo codice. È questo il vero codice che stavi correndo?

+0

Ciao Andrey. 1-> Il codice è in fase di compilazione. Dovrei preoccuparmi del casting esplicito allora? ... 2-> Sì, non ero a conoscenza di questo, a cui KennyTM ha risposto ... 3-> Ho menzionato, è un codice fittizio –

+1

@Gaurav Kalra: Compilare come cosa? Hai taggato la tua domanda [C] e [C++]. Questo codice non verrà compilato come C++ da alcun compilatore C++ che si rispetti. I compilatori C con controllo degli errori eccessivamente rilassato potrebbero consentire (con un avvertimento), ma il codice è ancora illegale anche come C, quindi se ti interessa scrivere un codice C valido è necessario il cast. – AnT