Hallo,
ich habe mal eine Grundfrage. Wann und wozu werden Pointer verwendet und
wann nicht? Wozu muss ich wissen auf welcher Adresse eine Variable
liegt? Warum kompliziert über zwei Pointer eine Variable ändern wenn ich
es auch direkt machen kann?
Danke für Eure Hinweise im Vorfeld.
Grüße
Peter
z.B.:
Wenn eine Funktion eine Variable ändern können soll, muss sie die
Adresse wissen, wo sie ändern soll.
und auch:
Es ist wesentlich effektiver, an eine Funktion Pointer auf Strings oder
structs zu übergeben, als die Daten selber.
Peter schrieb:> Hallo,> ich habe mal eine Grundfrage. Wann und wozu werden Pointer verwendet und> wann nicht?
C-Buch. Ehrlich!
> Wozu muss ich wissen auf welcher Adresse eine Variable> liegt?
Die konkrete Adresse (als Zahl) interessiert in der Tat fast niemanden.
Ergo ist deine Annahme schon mal falsch, du musst es nicht wissen. Aber
du willst vielleicht einen Pointer auf eine Variable zeigen lassen.
> Warum kompliziert über zwei Pointer eine Variable ändern wenn ich> es auch direkt machen kann?
Direkt geht halt nicht immer.
Der häufigste Fall: Du hast eine Struktur (struct) und eine Funktion
soll nun Daten generieren und diese in die Struktur eintragen. Dann
übergibst du einen Pointer auf diese Struktur an die Funktion. Die
Funktion trägt die Daten ein. Wie willst du das "direkt" lösen?
Damit du z.B. in einer Funktion ein ganzes Array beschreiben kannst und
du nur ein Wert übergeben musst(Adresse des ersten Speicherplatzes).
Oder um in einer Unterfunktion die Variable, die im main definiert ist,
zu verändern.
Pointer sind hilfreich, um globale Variablen zu vermeiden.
Am liebsten würde ich sagen:
Wenn du keinen Bedarf an Pointern hast, dann brauchst du sie auch nicht.
Aber:
Pointer/Zeiger/Adressen werden dauernd verwendet....
z.B. Beim durchlaufen von Arrays und Strings
Wenn auch nicht unbedingt explizit, aber im Hintergrund dann doch.
Wie schon gesagt wurde: Sobald man Array und Strings verwendet nutzt man
schon Pointer, auch wenn man es als Laie nicht direkt sieht. Pointer
können das Leben unglaublich vereinfachen…aber auch unglaublich
erschweren. Aber im Prinzip sind auch Pointer kein Hexenwerk, man
braucht wie bei so vielem einfach nur etwas Übung damit.
Ich kann mich da nur anschließen.
Grade wenn du Objektorientiert programmierst wird es echt mühselig alles
bei Call by value zu realisieren.
Du müstest ja dann immer jedes Objekt erzeugen wenn du es an eine
Funktion übergibst.
Oder wenn du Schnittstellen öffnest schließt verwendest... da wüsste ich
jertzt auf anhieb gar nicht wie das ohne pointer gehen sollte.
Wozu hast du eine Adresse? Damit dir jemand was schicken kann und weiss
wohin er das schicken soll.
Wozu braucht man in einer Programmiersprache eine Adresse? Damit jemand
(eine Funktion/Prozedur) weiss wo sie für dich ein Ergebnis hinschreiben
soll.
Danke für eure Hilfe. Das heißt also im Prinzip, bevor ich ein Objekt in
eine Funktion übergebe ist es einfacher die Adresse von dem Objekt zu
übergeben und dann direkt die Variable auf dieser Adresse zu ändern?
Peter schrieb:> Danke für eure Hilfe. Das heißt also im Prinzip, bevor ich ein Objekt in> eine Funktion übergebe ist es einfacher die Adresse von dem Objekt zu> übergeben und dann direkt die Variable auf dieser Adresse zu ändern?
Was heißt einfacher? Wie sonst soll die Funktion Daten im Objekt ändern,
wenn du eine Kopie (by value) an die Funktion übergibst?
Soll die Funktion die Daten nur lesen, ist es in der Tat fast egal. Aber
auch hier übergibt man meist einen Pointer.
> ... bevor ich ein Objekt übergebe ...
Manchmal willst du ein Objekt übergeben, manchmal eine Kopie des
Objektes.
Vielleicht liegt der Knoten hier: In C kannst du kein Objekt übergeben.
In C kannst du nur Pointer oder Kopien übergeben.
War vielleicht ein Fehler in der C-Denkweise. Hat sich aber so
eingebürgert und wird sich nicht mehr ändern. Wenn du einfach nur
Objekte übergeben willst, brauchst du Pointer.
Noch einer schrieb:> Vielleicht liegt der Knoten hier: In C kannst du kein Objekt übergeben.> In C kannst du nur Pointer oder Kopien übergeben.>> War vielleicht ein Fehler in der C-Denkweise
Ich sehe das genau umgekehrt:
Was ein Objekt ausmacht sind seine Daten. Ob man nun die Zahl 10 an zwei
unterschiedlichen Orten hat ist egal, es bleibt eine 10. In C kann man
Objekte mit all ihren Eigenschaften übergeben, man erhält dann effektiv
eine Kopie. Wenn man aber ein bestehendes Objekt referenzieren will,
muss man das explizit angeben und sieht das an einem schönen Pointer.
Andere Programmiersprachen machen das nicht so gut, egal ob Java,
JavaScript, PHP, Python, etc. Dort wird das verschleiert. Wenn man dann
behauptet, ein "Objekt" zu übergeben, wird dort nur eine Objektreferenz
und nicht wirklich das Objekt (aka dessen Daten) übergeben.
Ich vermute dass der Fragesteller sich auf Pointer bei mikrocontrollern
bezieht, nicht auf den Sinn von pointern generell, das kann man nämlich
leicht nachlesen.
Bei controllern mit wenig Speicher, kann manuelle Speicherverwaltung
sinnvoll sein und den Speicher wirklich komplett auszunutzen. Dabei
braucht man dann poiter.
Hier geht es ja auch noch öfter mal um 8 bit controller und da ist
Objektorientierte programmierung eher die Ausnahme.
Und noch ein Grund: Ein Pointer ist nur so breit wie für die RAM
Adressierung notwendig, für 32kB RAM also zum Beispiel 32 Bit.
Wenn hinter dieser Speicherstelle ein längerer String steht (diverse
kB), ist es auf jeden Fall deutlich performanter zu sagen "Da an Adresse
x findest du den String" als den kompletten String einmal quer durch den
RAM zu schieben.
Das gilt natürlich auch für beliebige andere Datentypen die etwas mehr
Speicherplatz als ein Integer belegen.
Sascha schrieb:> Und noch ein Grund: Ein Pointer ist nur so breit wie für die RAM> Adressierung notwendig, für 32kB RAM also zum Beispiel 32 Bit.>prust
Zeit für Feierabend?
Peter schrieb:> Hallo,> ich habe mal eine Grundfrage. Wann und wozu werden Pointer verwendet und> wann nicht? Wozu muss ich wissen auf welcher Adresse eine Variable> liegt? Warum kompliziert über zwei Pointer eine Variable ändern wenn ich> es auch direkt machen kann?
Indirekte Addressierung:
https://de.wikipedia.org/wiki/Adressierung_%28Rechnerarchitektur%29https://en.wikipedia.org/wiki/Addressing_mode#Simple_addressing_modes_for_data
mit postinkrement vom Maschinencode direkt unterstütz und dadurch
besonders schnell und ideal für Skalarprodukte (braucht man bei der DSP)
C-Buch ist da eine schlecuhter Ratgeber aber jedes Assemblerbuch sollte
erhellen
MfG,
Lars B. schrieb:> Hier geht es ja auch noch öfter mal um 8 bit controller und da ist> Objektorientierte programmierung eher die Ausnahme.
Das liegt nicht an den 8 bit sondern an der Art und Weise wie diese
Leute programmieren gelernt (oder nicht gelernt) haben. Wenn es sich
anbietet Daten als Objekte und Funktionen als Methoden derselben zu
behandeln weil man dann mit übersichtlicherem und meist auch mit weniger
Code auskommt dann tut man das einfach, ganz egal wie viel oder wenig
Bits die CPU hat.
ist ein Pointer auf den Speicherbereich den "meinarray" bezeichnet
sprich anfängt.
Jede Funktion/Prozedur ist ebenfalls ein Pointer der auf den
Speicherbereich zeigt wo die Funktion/Prozedir anfängt.
Das kann man in Assembler gut erkennen, da dort mittels jmp
hingesprungen wird.
Explizit Pointer zu nehmen kommt für Datenstrukturen in Frage oder man
kann einen void Pointer nehmen und damit alles mögliche veranstalten,
wenn man denn weiß was man tut.
Je nach Zielsystem ist der Pointer xbit lang und kann daher auch nur
2^xbit adressieren.
Der PC in der CPU ist nichts anderes als der Pointer der auf den
Speicherbereich zeigt der als nächstes gelesen und ausgeführt wird.
Wenn Du konkretere Fragen hast dann frage nachdem Du ein passendes Buch
für die Programmiersprache XYZ durchgelesen hast und da was unklar ist.
Peter schrieb:> ich habe mal eine Grundfrage. Wann und wozu werden Pointer verwendet und> wann nicht?
Wenn ein und dieselbe Programmstelle mal eine Variable und zu einem
anderen Durchlauf eine andere Variable (zum lesen und ggf. verändern)
benutzen soll.
Sind die Variablen Elemente eines Array, geht auch indizierter
Arrayzugriff a[i], sind es aber Variablen aus unterschiedlichen Quellen
r, s geht nur der Pointer a=&r, a=&s
Ich habe gelernt: willste was am Klavier ändern/reparieren bring nicht
das schwere Klavier zum klaviermacher sonder lass den Klaviermacher zum
schweren klavier kommen.
Peter schrieb:> Hallo,> ich habe mal eine Grundfrage. Wann und wozu werden Pointer verwendet und> wann nicht? Wozu muss ich wissen auf welcher Adresse eine Variable> liegt? Warum kompliziert über zwei Pointer eine Variable ändern wenn ich> es auch direkt machen kann?
Beispiel: Bildwiederholspeicher -
Lösche (Bildschirmspeicher mit = füllen) ohne pointer
mov addr_video+0 <- 0x00
mov addr_video+1 <- 0x00
mov addr_video+2 <- 0x00
...
mov addr_video+nuofpixel <- 0x00
mit pointer
loop:
mov reg <- nuofpixel
mov index_reg <- addr_video
mov (index_reg) <- 0x00
inc index_reg
dec reg
jmpnz loop
6 zeilen code
MfG,
Fpga K. schrieb:> mit postinkrement vom Maschinencode direkt unterstütz und dadurch> besonders schnell und ideal für Skalarprodukte (braucht man bei der DSP)
C wiederspiegelt solche Maschinenstrukturen. In den 70ern spielte das
eine Rolle, wenn der Compiler auf damaligen Rechnern unterhalb der
Mainframes laufen sollte.
Aber die Zeit, in der explizite Pointer-Wanderungen eine grössere Rolle
bei der Effizienz des erzeugten Codes spielten, die ist längst vorbei.
Heutige Compiler implementieren auch Schleifen mit Index über
inkrementierte Adressregister, wenn sinnvoll.
Emfehlenswerter Lehrbuchklassiker: "Algorithmen und Datenstrukturen"
Und hier: kleine Flohzirkuswelt.
Nur über Referenzen auf Daten wird gesprochen, die dicke Post der
Informatik geht aber erst richtig los mit Funktionspointer.
Elementarbeispel Sortierung: vergleiche und ggfs. tausche.
Blöd halt dass structs nicht einfach per ==/</> zu vergleichen sind.
Also muss eine generische Implementation eines Sortieralgorithmus
nicht die von der Programmiersprache mitgebrachten Operatoren vewenden,
sonder der Anwender des Algorithmus gibt da ein Pointer auf eine für die
jeweiligen (komplexen, nicht nativen) Datentypen passende
Vergleichsfunktion mit.
Anderes Beispiel: zur Laufzeit flexibel konfigurierbare zeitgesteuerte
Abläufe.
Wenn die Zeit gekommen ist, führe aus was dann "auf der Liste steht".
Also müssen zu gegebener Zeit Funkionen aufgerufen werden, welche weder
beim Compilieren noch beim starten des uCs ausgewählt sind: der Anwender
kann ja erst bei gestartetem System "die Liste für Übermorgen 13:45
zusammenstellen"...