Ist es schlecht, auf Array-Elemente über Zeigerarithmetik anstelle des Operators [] zu verweisen?


12

Ich habe gerade angefangen, C zu lernen, und um das Verständnis von Zeigern und Arrays zu verbessern, habe ich versucht, auf die Elemente eines Arrays zu verweisen, ohne überhaupt einen Zeiger zu erstellen:

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));

    }
}

Der gesamte Code wird kompiliert und funktioniert einwandfrei.

Ich stelle mir vor, für jedes einzelne Array in einem großen Quellcode einen Zeiger erstellen zu müssen, ist höchst ineffizient.

Ist es also eine schlechte Programmierpraxis, die Adresse des Arrays direkt zu verwenden, anstatt die Adresse eines Arrays mit einem Zeiger speichern und abrufen zu lassen, wie oben gezeigt?


Die Verwendung printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));würde die Zeigerarithmik umgehen und ist einfacher zu verstehen.
Kasper van den Berg

1
Haha, du hast mich erwischt. Ich habe das nur als Experiment durchgeführt, um besser zu verstehen, wie Zeiger und Arrays funktionieren.
Niko Gambt,

Die Zeigerarithmetik ist tatsächlich etwa 30% schneller als die Verwendung von Array-Indizes.
Andy

Antworten:


16

Es ist nur insoweit "schlecht", als es weniger lesbar ist. a[x]ist das Gleiche wie *(a+x), so gibt es keinen Unterschied in Effizienz oder Verhalten (in der Tat x[a]wird auch funktionieren). Es ist nur so, dass a[x]es für uns Menschen normalerweise viel intuitiver ist.

Das heißt aber nicht, dass Lesbarkeit keine große Sache ist. Überlegen Sie, wie Sie diese beiden Ausdrücke "lesen" würden, wenn Sie sie im Code sehen würden, um zu sehen, wie groß sie sind:

  • *(a+x)= "Das Ding, auf das durch die Summe von Zeiger aund Ganzzahl gezeigt wird x"
  • a[x]= "Das xdritte Mitglied des Arrays a"

Ebenso, wenn Sie auf die Adresse eines Array-Elements verweisen müssen:

  • (a+x)= "Die Summe von Zeiger aund Ganzzahl x"
  • &a[x]= "Die Adresse des xdritten Mitglieds des Arrays a"

Meistens sind die []Versionen einfacher zu verstehen, wenn Sie nicht-trivialen Code betrachten, der auf mehreren verschiedenen Arrays (insbesondere Arrays von Arrays) ausgeführt wird. Deshalb gibt es den []Operator überhaupt.

PS Es ist eine sehr gute Idee, so etwas nur als Lernübung zu machen. Es ist wichtig zu verstehen, dass Arrays wirklich nur Zeiger und Offsets sind.


Dies. Vielen Dank. Ich habe gerade festgestellt, dass ich wirklich wissen möchte, ob es notwendig ist, auf die Adresse eines Array-Elements und dann auf die Adresse eines anderen Elements zu verweisen, und dann auf ein anderes, ist es immer noch schlecht NICHT einen Zeiger zu benutzen und stattdessen das Array direkt so zu benutzen, wie ich es getan habe? Meine Frage war wirklich schwer zu beantworten, deshalb habe ich sie nicht im OP eingegeben. Wie auch immer, da ich nicht danach gefragt habe, ist Ihre Antwort zufriedenstellend.
Niko Gambt,

1
@NikoGambt Sie können immer eine andere Frage stellen =)
Ixrec

1
Was meinst du nur soweit ...? Der Sinn der Programmiersprachen besteht darin, den Code für den Menschen leichter lesbar zu machen. Wenn uns das egal wäre, würden wir alle Operationscodes hexadezimal schreiben.
Solomon Slow

2
Arrays sind keine Zeiger, die implizit nur auf Zeiger zerfallen.
CodesInChaos

4

Ja, es ist eine schlechte Praxis, aber nicht aus Gründen der Ineffizienz.

Der Array-Operator verwendet Zeiger-Arithmetik unter der Haube, sodass sie gleichermaßen effizient sind.

Das Problem mit der Zeigerarithmetik ist, dass sie sehr fehleranfällig und schwerer zu lesen ist.

Faustregel: Verwenden Sie keine Zeigerarithmetik, es sei denn, Sie müssen.


1
Bedeutet das nicht, dass Zeiger genauso fehleranfällig und schwer zu lesen sind, da sie sowieso Zeigerarithmetik verwenden?
Niko Gambt,

1
@NikoGambt-Compiler sind ziemlich gut darin, Zeiger-Arithmen unter der Haube auszuführen und machen selten 'Fehler'. Es sind die Programmierer, die in der Folge Fehler mit bösen Bugs machen.
Kasper van den Berg

@KaspervandenBerg Ja, ich stimme zu. Ich bin jedoch an Fehlern interessiert, die von Programmierern gemacht wurden, und ich bin mir nicht ganz sicher, ob es eine schlechte Programmierpraxis ist, das zu tun, was ich oben gemacht habe, in Fällen, in denen die Adresse eines Arrays angegeben werden muss , falls solche Fälle vorliegen.
Niko Gambt,

1
@NikoGambt Etwas zu schreiben, das für Performancezwecke weniger lesbar ist, ist fast immer eine schlechte Übung, aber etwas zu schreiben, das für keinen Gewinn weniger lesbar ist, ist eindeutig eine schlechte Übung.
Neil

@Neil Mein kleines Experiment ist nicht sinnlos. Dadurch habe ich gelernt, dass der Compiler ein Array von Zeigern zu erstellen scheint, die auf ein mehrdimensionales Array verweisen. Da Sie jedoch sagten, Lesbarkeit sei wichtiger als Leistung, ist dies vermutlich immer noch eine schlechte Programmierpraxis.
Niko Gambt,

0

Cool your learning c, du hast gerade einen kleinen Zungenbrecher entdeckt. Sie führen keine Zeigerarithmetik für ein Array aus, sondern für ein Array von Zeigern. Das Ausführen von Zeigerarithmetik für Arrays ist nicht möglich. Ein Array verwandelt sich in einen Zeiger, ist jedoch kein Zeigertyp. Was du mein hast (siehe Kommentar von cmaster) ist

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  

Die Referenzierung dieses Zeigers gibt den Wert an, auf den Ihr gerade berechneter Zeiger zeigt. Im Allgemeinen macht es keinen Sinn, das zu tun, was Sie tun. Aber Sie können das Array linearisieren und dann einen Schritt darin machen.

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

Schritt sie ist x_dim. Hoffe meine Antwort klärt sich!


Aus dem OP ist nicht ersichtlich, ob int* array[ROW];ein int array[ROW][COLUMN];oder ein verwendet wird int (*array)[COLUMN];. Jede dieser drei Definitionen kann mit dem Code im OP verwendet werden.
cmaster

Ja, mir ist das bewusst, meine Antwort ist in diesem Punkt etwas unbeholfen. Ich korrigiere es, danke!
Fhtuft
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.