Wie versteht man Zeigerarithmetik??
-
Namal schrieb:
Wieso werden in einem Vektor/Array bei C/C++ die Element von 0 bis n-1 nummeriert und nicht von 1 bis n?
Es ist einfach konsequenter von 0 zu starten. Ausserdem macht es einige Rechnungen kürzer.
vec[i % vec.size()] vs. vec[i % vec.size() + 1] vec[i/2] vs vec[(i-1)%2+1]Why numbering should start at zero
Wikipedia: Zero-based numbering
-
Belli schrieb:
Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?
Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.
-
out schrieb:
Im Übrigen kannst du auch den Variablennamen als Offset hernehmen, also kannst statt Zahl[0] auch 0[Zahl] schreiben.
Bei einem std::vector oder einem std::array geht das schon nicht mehr.
-
Namal schrieb:
Belli schrieb:
Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?
Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.
Weil die 0 eben vor der 1 kommt?
Außerdem macht das wie gesagt wegen Offets Sinn.arr[0] ist äquivalent zu arr + 0
arr[1] ist äquivalent zu arr + 1*sizeof(*arr)
arr[2] ist äquivalent zu arr + 2*sizeof(*arr)etc
-
out schrieb:
Informatiker mögen halt die 0. :p Wenn etwas nicht bei 0 beginnt, bin ich verwirrt.
So einfach kann es nicht sein. Es gibt Programmiersprachen, bei denen der Index bei 1 beginnt.
-
Belli schrieb:
Ein Pointer AUF das Array wäre übrigens:
int *pZahl = Zahl;oder von mir aus auch:
int *pZahl = &Zahl[0];Nein, jetzt hast du einen Pointer auf ein char. Wenn du ein Pointer auf das Array willst, musst du schon
int (*pZahl)[5] = &Zahl;schreiben.
-
Belli schrieb:
Nein, sie könnten auch mit 17 anfangen. Tun sie aber einfach nicht.
Es gibt einen ganz eindeutigen Grund, wieso sie mit 0 Anfangen, und wieso es deutlich weniger Sinn hat dass das erste Element den Index 17 hat.
Ein Array (ich spreche hier sowohl von echten Arrays als auch von sequentiellen STL-Containern) hält intern einen Zeiger auf das erste Element.
int a[] = {1, 2, 3};Dank dem array to pointer decay kann
asogar implizit in einen Zeiger auf das erste Element konvertiert werden - weilaintern genau diesen Zeiger hält, redet man von decay - engl. für Zerfall; a kann also zu diesem Zeiger zerfallen.Natürlich hat
anicht den Typint*!
Sondernint[3].und was macht jetzt der Index-Operator?
Ganz einfach.a[x]Ist dasselbe (bzw. implementiert durch)
*(a + x) // a zerfällt in der Summe in einen Zeiger. Dieser wird um x Elemente verschoben und dereferenziert.Man sieht sofort: Will man auf das erste Element zugreifen, dann muss man nur 0 angeben.
Dann ergibt der Ausdruck*(a + 0)
*aUnd weil (wie oben besprochen)
aimplizit in einen Zeiger auf das erste Element konvertiert werden kann, ist das Ergebnis dieses Ausdrucks eine Referenz auf das erste Element.Die obige Methode ist einfach und performant. Die zusätzliche 17 in der Summe wäre schlicht und einfach unnötig und könnte sich möglicherweise auch auf die Performance auswirken (da weiß ich leider nix näheres), was, selbst so klein die Auswirkung auch sein mag, bei sehr großen Arrays und vielen Iterationen durchaus eine maßgebende Bedeutung haben kann.
-
dijkstra schrieb:
Bei einem std::vector oder einem std::array geht das schon nicht mehr.
Das sind ja auch nutzerdefinierte Datentypen (wobei der "Nutzer" der STL-Hersteller ist). Du kannst dir gerne einen eigenen Datentypen basteln, der ein Offset erlaubt.
-
Ethon schrieb:
Namal schrieb:
Belli schrieb:
Keine Ahnung, aber warum nicht von 17 bis 17 + n - 1?
Ja warum eigentlich nicht? Würde genausoviel Sinn machen wie jetzt.
Weil die 0 eben vor der 1 kommt?
Außerdem macht das wie gesagt wegen Offets Sinn.arr[0] ist äquivalent zu arr + 0
arr[1] ist äquivalent zu arr + 1*sizeof(*arr)
arr[2] ist äquivalent zu arr + 2*sizeof(*arr)etc
Du hast
*( ~ )vergessen :xmas1:Verdammt, viel zu spät!

-
out schrieb:
Belli schrieb:
Ein Pointer AUF das Array wäre übrigens:
int *pZahl = Zahl;oder von mir aus auch:
int *pZahl = &Zahl[0];Nein, jetzt hast du einen Pointer auf ein char. Wenn du ein Pointer auf das Array willst, musst du schon
int (*pZahl)[5] = &Zahl;schreiben.
Humbug!
-
Belli schrieb:
Humbug!

-
out schrieb:
Nein, jetzt hast du einen Pointer auf ein char.
char, wie komm ich auf char
ich meinte natürlich int.Sone schrieb:
Ein Array (ich spreche hier sowohl von echten als auch von sequentiellen STL-Containern) ist intern einfach ein Zeiger auf das erste Element des Arrays im Speicher.
Nimm den Satz aus deinem Post raus.

-
out schrieb:
Sone schrieb:
Ein Array (ich spreche hier sowohl von echten als auch von sequentiellen STL-Containern) ist intern einfach ein Zeiger auf das erste Element des Arrays im Speicher.
Nimm den Satz aus deinem Post raus.

Korrigiert, ich schäme mich.

War im Eifer des Gefechts :xmas1:
-
silent_max schrieb:
Ich hoffe, dass es jetzt bisschen verständlicher wird??
Du hast (wie erwartet) vergessen die Begründungen mit anzugeben. Hat vielleicht was damit zu tun, dass 90% des Codes sinnlos ist.
-
Belli schrieb:
Humbug!
Was ist da Humbug? Wenn du int* p schreibst hast du nunmal einen Zeiger auf ein int. War schon immer so.
-
Na und?
Du hast behauptet, ich hätte einen Zeiger auf char.
-
out schrieb:
out schrieb:
Nein, jetzt hast du einen Pointer auf ein char.
char, wie komm ich auf char
ich meinte natürlich int.Es geht ja so schnell hier, da überliest man schonmal was. :p
-
Dann halt hier mit Begründungen:
#include<iostream> using namespace std; int main() { cout << "\t 5 Adressen um jeweils 4 Byte hochzaehlen lassen.\n"; cout << "\n"; int Zahl[5]; //Array mit 5 Elementen initialisieren, damit ich 5 Elemente habe int *pZahl = &Zahl[5]; //Pointer auf das Array initialisieren, damit ich auf die Adressen des Arrays zugreifen kann int a; // Variable deklarieren, damit ich fuer cin nachher Werte eingeben kann und diesmal nicht i habe cout << "Geben Sie fuenf Zahlen ein.\n"; for(int i=0; i<5; i++) { cout << "Zahl[" << i <<"]: "; //Für Elemente von 0 bis 4 Werte bzw. Zahlen eingeben cin >> a; //Variable a fuer die Werteeingabe, damit ich z. B. 1,2,3,4,5 eigeben kann } cout << "Die Adresse der jeweiligen Zahl lautet wie folgt:\n"; for(int i=0; i<5; i++) { cout << "Zahl[" << i << "]: " << &Zahl[i] << "\n"; // Adresse fuer die Elemente 0 bis 4 ausgeben, also fuer insgesamt 5 Elemente( Element 0, Element 1, Element 2, Element 3, Element 4 sind nun mal 5 Elemente oder rechne ich falsch??????????????) } return 0; }[quote="cooky451"]
silent_max schrieb:
Du hast (wie erwartet) vergessen die Begründungen mit anzugeben. Hat vielleicht was damit zu tun, dass 90% des Codes sinnlos ist.
Und da Du den Code schon länger als sinnlos erachtest, bitte ich Dich darum, einen äquivalenten Code zu schreiben, der die Speicheradressen von insgesamt
5 Elementen ausliest....
-
silent_max schrieb:
Und da Du den Code schon länger als sinnlos erachtest, bitte ich Dich darum, einen äquivalenten Code zu schreiben, der die Speicheradressen von insgesamt
5 Elementen ausliest....Was ist der Sinn von folgende Zeilen: 10, 11, 15-19, 28? Was passiert, wenn du sie weglässt? Was hat die Ausgabe in Zeile 6 mit dem zu tun, was das Programm tatsächlich macht?
-
SeppJ schrieb:
Was ist der Sinn von folgende Zeilen: 10, 11, 15-19, 28? Was passiert, wenn du sie weglässt? Was hat die Ausgabe in Zeile 6 mit dem zu tun, was das Programm tatsächlich macht?
Ich wollte halt von 5 Elementen, die ich von der Tastatur einlese, die Adresse auslesen lassen.
Dass man Zeile 10 prinzipiell weglassen kann, habe ich erst im Laufe des Threads mitbekommen.
Edit:
Was ich dazu sagen sollte:
Ich wollte einfach ein Programm schreiben, das mir von 5 Elementen die ich per Tastatur einlese, um am Beispiel meines Programms zu bleiben von int, in 4 Byte Abständen die Speicheradressen auslesen lassen. Nicht mehr und auch nicht weniger