arrays Con gli array, perché è il caso di un [5] == 5 [a]?




8 Answers

Perché l'accesso dell'array è definito in termini di puntatori. a[i] è definito come *(a + i) , che è commutativo.

c arrays pointers pointer-arithmetic

Come sottolinea Joel in podcast # 34 , in C Programming Language (aka: K & R), c'è menzione di questa proprietà degli array in C: a[5] == 5[a]

Joel dice che è a causa dell'aritmetica del puntatore, ma io ancora non capisco. Perché a[5] == 5[a] ?




E naturalmente

 ("ABCD"[2] == 2["ABCD"]) && (2["ABCD"] == 'C') && ("ABCD"[2] == 'C')

Il motivo principale per questo era che negli anni '70, quando C fu progettato, i computer non avevano molta memoria (64 KB erano molti), quindi il compilatore C non eseguiva molto controllo della sintassi. Quindi " X[Y] " è stato tradotto alla cieca in " *(X+Y) "

Questo spiega anche le sintassi " += " e " ++ ". Tutto nella forma " A = B + C " aveva la stessa forma compilata. Ma, se B era lo stesso oggetto di A, allora era disponibile un'ottimizzazione del livello di assemblaggio. Ma il compilatore non era abbastanza brillante da riconoscerlo, quindi lo sviluppatore doveva ( A += C ). Allo stesso modo, se C era 1 , era disponibile un'ottimizzazione del livello di assemblaggio diversa, e ancora lo sviluppatore doveva renderlo esplicito, perché il compilatore non lo riconosceva. (Più recenti compilatori, quindi quelle sintassi sono in gran parte inutili in questi giorni)




Per rispondere alla domanda alla lettera. Non è sempre vero che x == x

double zero = 0.0;
double a[] = { 0,0,0,0,0, zero/zero}; // NaN
cout << (a[5] == 5[a] ? "true" : "false") << endl;

stampe

false



Ho appena scoperto che questa brutta sintassi potrebbe essere "utile", o almeno molto divertente da giocare quando si vuole gestire una serie di indici che si riferiscono a posizioni nello stesso array. Può sostituire parentesi quadre annidate e rendere il codice più leggibile!

int a[] = { 2 , 3 , 3 , 2 , 4 };
int s = sizeof a / sizeof *a;  //  s == 5

for(int i = 0 ; i < s ; ++i) {  

           cout << a[a[a[i]]] << endl;
           // ... is equivalent to ... 
           cout << i[a][a][a] << endl;  // but I prefer this one, it's easier to increase the level of indirection (without loop)

}

Certo, sono abbastanza sicuro che non ci sia un caso d'uso per questo nel codice reale, ma l'ho trovato comunque interessante :)




Non una risposta, ma solo qualche spunto di riflessione. Se la classe sta sovraccaricando l'operatore indice / pedice, l'espressione 0[x] non funzionerà:

class Sub
{
public:
    int operator [](size_t nIndex)
    {
        return 0;
    }   
};

int main()
{
    Sub s;
    s[0];
    0[s]; // ERROR 
}

Dal momento che non abbiamo accesso alla classe int , questo non può essere fatto:

class int
{
   int operator[](const Sub&);
};



So che la domanda è stata risolta, ma non ho potuto resistere alla condivisione di questa spiegazione.

Ricordo il disegno Principles of Compiler, Supponiamo che sia un array int e che la dimensione di int sia 2 byte, e l'indirizzo di base di a sia 1000.

Come funziona a[5] ->

Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

Così,

Allo stesso modo quando il codice c è scomposto in un codice a 3 indirizzi, 5[a] diventerà ->

Base Address of your Array a + (size of(data type for array a)*5)
i.e. 1000 + (2*5) = 1010 

Quindi fondamentalmente entrambe le istruzioni puntano alla stessa posizione in memoria e quindi, a[5] = 5[a] .

Questa spiegazione è anche la ragione per cui gli indici negativi negli array funzionano in C.

cioè se accedo a[-5] mi darà

Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

Mi restituirà l'oggetto nella posizione 990.




nel compilatore c

a[i]
i[a]
*(a+i)

sono diversi modi per fare riferimento a un elemento in un array! (NON A TUTTO IL WEIRD)




Bene, questa è una funzionalità che è possibile solo grazie al supporto della lingua.

Il compilatore interpreta a[i] come *(a+i) e l'espressione 5[a] valuta su *(5+a) . Poiché l'addizione è commutativa, risulta che entrambi sono uguali. Quindi l'espressione è true .




Related