È male fare riferimento all'accesso agli elementi dell'array tramite l'aritmetica del puntatore anziché l'operatore []?


12

Ho appena iniziato a imparare a programmare in C e, per migliorare la mia comprensione di puntatori e matrici, ho provato a fare riferimento agli elementi di un array senza creare alcun puntatore:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

L'intero codice viene compilato ed eseguito in modo impeccabile.

Immagino che dover creare un puntatore per ogni singolo array in un grande codice sorgente sembra essere altamente inefficiente.

Quindi, piuttosto che avere l'indirizzo di un array archiviato e recuperato usando un puntatore, è una cattiva pratica di programmazione usare direttamente l'indirizzo dell'array, come mostrato sopra?


L'uso printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));eviterebbe il puntatore aritmico ed è più facile da capire.
Kasper van den Berg,

1
Haha, mi hai preso. L'ho fatto solo come esperimento per comprendere meglio come funzionano i puntatori e le matrici.
Niko Gambt,

L'aritmetica del puntatore è in realtà circa il 30% più veloce rispetto all'utilizzo degli indici di array.
Andy,

Risposte:


16

È "cattivo" solo nella misura in cui è meno leggibile. a[x]è la stessa cosa di *(a+x), quindi non c'è differenza di efficienza o comportamento (in effetti, x[a]funzionerà anche). È solo che di a[x]solito è molto più intuitivo per noi umani.

Ma questo non vuol dire che la leggibilità non è un grosso problema. Per vedere quanto è grande, pensa a come "leggere" queste due espressioni se le vedessi nel codice:

  • *(a+x)= "La cosa indicata dalla somma di puntatore ae intero x"
  • a[x]= "Il xmembro th dell'array a"

Allo stesso modo, quando è necessario fare riferimento all'indirizzo di un elemento array:

  • (a+x)= "La somma di puntatore ae numero intero x"
  • &a[x]= "L'indirizzo del xmembro th dell'array a"

Il più delle volte, le []versioni sono semplicemente più facili da capire quando si osserva un codice non banale che opera su diversi array diversi (in particolare array di array). Ecco perché l' []operatore esiste in primo luogo.

PS Fare questo tipo di cose rigorosamente come un esercizio di apprendimento è un'ottima idea. È importante capire che le matrici sono in realtà solo puntatori e offset.


Questo. Grazie. Ho appena capito in fondo che cosa voglio veramente sapere è se, quando c'è la necessità di fare riferimento all'indirizzo di qualsiasi elemento dell'array, quindi fare riferimento all'indirizzo di un altro elemento, e poi un altro, è ancora male NON usare un puntatore e, invece, usare l'array direttamente come ho fatto io? Questa mia domanda è stata davvero difficile da individuare, ecco perché non l'ho inserita nel PO. Comunque, dato che non l'ho chiesto, la tua risposta è soddisfacente.
Niko Gambt,

1
@NikoGambt Puoi sempre fare un'altra domanda =)
Ixrec il

1
Cosa intendi solo nella misura in cui ...? L'intero punto dei linguaggi di programmazione è rendere il codice più facile da leggere per gli umani. Se non ci importasse, scriveremmo tutti i codici operativi in ​​esadecimali.
Solomon Slow,

2
Le matrici non sono puntatori, il solo decadimento implicito dei puntatori.
CodesInChaos,

4

Sì, è una cattiva pratica, ma non per motivi di inefficienza.

L'operatore dell'array utilizza l'aritmetica del puntatore sotto il cofano, quindi è altrettanto efficiente.

Il problema con l'aritmetica del puntatore è che è molto soggetto a errori e più difficile da leggere.

Regola empirica: non utilizzare l'aritmetica del puntatore a meno che non sia necessario.


1
Dal momento che utilizza l'aritmetica dei puntatori, ciò non significa che anche i puntatori sono ugualmente soggetti a errori e difficili da leggere?
Niko Gambt,

1
I compilatori di @NikoGambt sono abbastanza bravi a fare puntatori aritmici sotto il cofano e raramente commettono "errori"; sono i programmatori che faranno errori con cattivi bug di conseguenza.
Kasper van den Berg,

@KaspervandenBerg Sì, sono d'accordo. Tuttavia, sono interessato agli errori commessi dai programmatori e non sono del tutto sicuro che sia una cattiva pratica di programmazione fare ciò che ho fatto sopra, nei casi in cui è necessario fare riferimento all'indirizzo di un array , se esistono casi del genere.
Niko Gambt,

1
@NikoGambt Scrivere qualcosa che è meno leggibile a fini prestazionali è quasi sempre una cattiva pratica, ma scrivere qualcosa che è meno leggibile per nessun guadagno è inequivocabilmente cattiva pratica.
Neil,

@Neil Il mio piccolo esperimento non ha senso. In questo modo, ho imparato che il compilatore sembra creare una matrice di puntatori per fare riferimento a una matrice multidimensionale. Tuttavia, dal momento che hai detto che la leggibilità è più importante delle prestazioni, immagino che sia ancora una cattiva pratica di programmazione.
Niko Gambt,

0

Raffredda il tuo apprendimento c, hai appena scoperto uno dei piccoli scioglilingua. Non si esegue l'aritmetica dei puntatori su un array, ma un array di puntatori. Non è possibile eseguire l'aritmetica del puntatore sugli array. Un array decade in un puntatore ma non è un tipo di puntatore stesso. Quello che possiedi (vedi commento di cmaster) è

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

Dereferenziare questo puntatore dà il valore a cui punta il puntatore appena calcolato. In genere non ha senso fare quello che stai facendo. Ma puoi linearizzare l'array e poi un passo avanti in questo modo.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

Stride her is x_dim. Spero che la mia risposta stia chiarendo!


Dall'OP non è chiaro se utilizza un int* array[ROW];an int array[ROW][COLUMN];o un int (*array)[COLUMN];. Entrambe queste tre definizioni possono essere utilizzate con il codice nell'OP.
cmaster - ripristina monica il

sì, ne sono consapevole, la mia risposta è un po 'goffa su questo punto. Lo correggo, grazie!
fhtuft
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.