Domanda

Supponiamo che abbiamo il seguente codice:

int main(){
    int a[3]={1,2,3};
    printf("      E: 0x%x\n", a);
    printf("  &E[2]: 0x%x\n", &a[2]);
    printf("&E[2]-E: 0x%x\n", &a[2] - a);
    return 1;
}

Quando compilati ed eseguiti, i risultati sono i seguenti:

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2

Comprendo il risultato di & amp; E [2] che è 8 più l'indirizzo dell'array, poiché indicizzato da 2 e di tipo int (4 byte sul mio sistema a 32 bit), ma io non riesci a capire perché l'ultima riga sia 2 anziché 8?

Inoltre, quale tipo di ultima riga dovrebbe essere: un numero intero o un puntatore intero?

Mi chiedo se è il sistema di tipo C (kinda casting) a fare questo bizzarro?

È stato utile?

Soluzione

Devi ricordare cosa significa veramente l'espressione a [2] . È esattamente equivalente a * (a + 2) . Tanto che è perfettamente legale scrivere 2 [a] , con identico effetto.

Affinché funzioni e abbia senso, l'aritmetica del puntatore tiene conto del tipo di cosa indicato. Ma questo è curato dietro le quinte. Puoi semplicemente utilizzare gli offset naturali nelle tue matrici e tutti i dettagli si risolvono.

La stessa logica si applica alle differenze del puntatore, il che spiega il risultato di 2 .

Sotto il cofano, nel tuo esempio l'indice viene moltiplicato per sizeof (int) per ottenere un offset di byte che viene aggiunto all'indirizzo di base dell'array. Esponi quel dettaglio nelle tue due stampe degli indirizzi.

Altri suggerimenti

Quando si sottraggono puntatori dello stesso tipo, il risultato è il numero di elementi e non il numero di byte. Questo è di progettazione in modo da poter facilmente indicizzare matrici di qualsiasi tipo. Se si desidera il numero di byte, eseguire il cast degli indirizzi su char *.

Quando si incrementa il puntatore di 1 (p + 1), il puntatore punta al prossimo indirizzo valido aggiungendo (p + sizeof (Type)) byte a p. (se Type è int, allora p + sizeof (int))

Una logica simile vale anche per p-1 (ovviamente sottrai in questo caso).

Se applichi questi principi qui:

In termini semplici:

a[2] can be represented as (a+2)
a[2]-a      ==>  (a+2) - (a)    ==> 2

Quindi, dietro le quinte,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2

La riga & amp; E [2] -2 sta eseguendo la sottrazione del puntatore, non la sottrazione dei numeri interi. La sottrazione del puntatore (quando entrambi i puntatori puntano a dati dello stesso tipo) restituisce la differenza degli indirizzi divisa per la dimensione del tipo a cui puntano. Il valore restituito è un int.

Per rispondere al tuo " aggiorna " domanda, ancora una volta l'aritmetica del puntatore (questa volta aggiunta del puntatore) viene eseguita. È stato fatto in questo modo in C per rendere più semplice "indicizzare" un blocco di dati contigui a cui punta il puntatore.

Potresti essere interessato a Puntatore aritmetico in C domande e risposte.

in pratica, gli operatori + e - tengono conto della dimensione dell'elemento quando usato sui puntatori.

Quando si aggiungono e sottraggono i puntatori in C, si utilizza la dimensione del tipo di dati anziché gli indirizzi assoluti.

Se hai un puntatore int e aggiungi il numero 2, avanzerà 2 * sizeof (int). Allo stesso modo, se si sottraggono due puntatori int, si otterrà il risultato in unità di sizeof (int) anziché nella differenza degli indirizzi assoluti.

(Avere puntatori che utilizzano la dimensione del tipo di dati è abbastanza conveniente, quindi ad esempio puoi semplicemente usare p ++ invece di dover specificare la dimensione del tipo ogni volta: p + = sizeof (int) ).

un numero intero / numero. per lo stesso motivo che il: oggi - 1 aprile = numero. non data

Se si desidera vedere la differenza di byte, è necessario un tipo di dimensioni pari a 1 byte, in questo modo:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top