Ich beschäftige mich aktuell mit C und Pointern.
Bei mir ist hängen geblieben, dass Pointer besonders im Embedded-Bereich
sinnvoll sind, wenn man keine so großen Ressourcen hat. Dann übergibt
man als Übergabeparameter nur die Adresse des Zeigers anstatt den ganzen
Wert ansich in eine neue Speicherstelle zu kopieren, richtig?
Wenn man jetzt einen externen Speicher nimmt anstelle OnChip, büßt man
dann nicht an Leistung ein?
Ich wüsste jetzt spontan nicht, wann ich einen Zeiger nehmen sollte.
Gibt es Daumenregeln, macht ihr das nach Gefühl, wird das üblicherweise
bereits zum Zeitpunkt der Spec/Design festgelegt und nicht erst bei der
Implementierung? Wovon macht ihr das abhängig?
Über eine Beispiel oder Erfahrungswerte würde ich mich freuen. Danke im
voraus.
Zeiger nimmt man primär, um verkettete Datenstrukturen aufzubauen.
Dein Beispiel ist völlig unabhängig von Embedded oder nicht und ein
vergleichsweise unwichtiges Detail. Der Hauptgrund für Zeiger ist
Indirektion. Konkrete Beispiele sind Legion, insofern ist es schwierig,
die zu nennen, die dich evtl. interessieren.
Such mal nach verketteter Liste. B-Tree. Menüs. Plugin-Architekturen.
@newbo (Gast)
>Wenn man jetzt einen externen Speicher nimmt anstelle OnChip, büßt man>dann nicht an Leistung ein?
Nein.
>Ich wüsste jetzt spontan nicht, wann ich einen Zeiger nehmen sollte.>Gibt es Daumenregeln, macht ihr das nach Gefühl, wird das üblicherweise>bereits zum Zeitpunkt der Spec/Design festgelegt
Meisten ja.
> und nicht erst bei der>Implementierung?
Manchmal.
> Wovon macht ihr das abhängig?
Einen Zeiger nimmt man wenn
- die Originaldaten beschrieben werden sollen
- die zu verarbeitenden Daten größer als eine normale Variable sind
(große Structs oder Arrays)
- Arrays werden IMMER als Zeiger übergeben
Wenn ich z.B in einer Funktion Berechnungen o.ä. durchführen möchte und
deren Parameter und Ergebnisse wieder in einer Vielzahl an Funktionen
verwendet werden soll, warum soll ich jedes mal bei der Übergabe an die
Funktion ein Duplikat anlegen und den Rückgabewert später auch wieder
umkopieren wenn ich genauso gut auch gleich mit den originalen arbeiten
kann?
Und noch ne andere Frage.
Wie gibst di mehr als einen Wert aus einer Funktion zurück?
@ Frank (Gast)
>Wenn ich z.B in einer Funktion Berechnungen o.ä. durchführen möchte und>deren Parameter und Ergebnisse wieder in einer Vielzahl an Funktionen>verwendet werden soll, warum soll ich jedes mal bei der Übergabe an die>Funktion ein Duplikat anlegen und den Rückgabewert später auch wieder>umkopieren wenn ich genauso gut auch gleich mit den originalen arbeiten>kann?
Weil du das Prinzip der Kapselung noch nicht verstanden hast. Eine
Funktion soll so weit wie möglich KEINERLEI unsichtbare Nebeneffekte
haben. Das erreicht man u.a. durch Funktionsparameter (welche Kopien
sind) und einem Rückgabeparameter. Es hat schon seinen Grund, warum es
in C normale Funktionsparameter (call by value) und Zeiger (call by
reference) gibt.
>Wie gibst di mehr als einen Wert aus einer Funktion zurück?
Mit einem Struct als Rückgabewert ;-)
Man sollte auch beachten, dass die Übergabe per Wert bei Typen mit
geringer Größe in der Regel schneller ist als die Zeigeroperationen, die
bei 'call by reference' nötig sind. Ich erwähne es nur mal, weil manche
Anfänger gleich übertreiben und "aus Performancegründen" auch bei char,
int usw. Zeiger (bzw. bei C++ auch Referenzen) verwenden.
Falk B. schrieb:> @ Frank (Gast)>>>Wenn ich z.B in einer Funktion Berechnungen o.ä. durchführen möchte und>>deren Parameter und Ergebnisse wieder in einer Vielzahl an Funktionen>>verwendet werden soll, warum soll ich jedes mal bei der Übergabe an die>>Funktion ein Duplikat anlegen und den Rückgabewert später auch wieder>>umkopieren wenn ich genauso gut auch gleich mit den originalen arbeiten>>kann?>> Weil du das Prinzip der Kapselung noch nicht verstanden hast. Eine> Funktion soll so weit wie möglich KEINERLEI unsichtbare Nebeneffekte> haben. Das erreicht man u.a. durch Funktionsparameter (welche Kopien> sind) und einem Rückgabeparameter. Es hat schon seinen Grund, warum es> in C normale Funktionsparameter (call by value) und Zeiger (call by> reference) gibt.>>>Wie gibst di mehr als einen Wert aus einer Funktion zurück?>> Mit einem Struct als Rückgabewert ;-)
Also nehme ich Pointer, wenn es um die Verarbeitung großer struct und
arrays geht. Ich versuche aber Pointer und die daraus resultierenden
unsichtbaren Nebeneffekte weitestgehend zu vermeiden, um eine hohe
Kapselung für mein Modul zu erreichen.
Bei char und int prüfe ich, ob deren Übergabe nicht schneller geht als
eine Zeigeroperation.
Richtig? Danke für die Tipps.
newbo schrieb:> Bei mir ist hängen geblieben, dass Pointer besonders im Embedded-Bereich> sinnvoll sind, wenn man keine so großen Ressourcen hat.
Die heutigen Compiler sind meistens nicht so doof, wie viele denken.
Man kann oft die Indexschreibweise benutzen und der Compiler wandelt das
selber in Pointer um.
Außerdem macht es der Index leichter, ein Argument auf
Feldüberschreitung zu testen und es ist nur ein Test nötig (Endwert).
Ein Test verhindert zwar nicht den Fehler, aber er verhindert, daß sich
der Fehler an einer völlig anderen Stelle auswirkt und man sich dumm und
dußlig sucht.
Ein falscher Pointerzugriff kann nämlich den Wert einer völlig anderen
Funktion verändern, die daran total unschuldig ist. Wenn es keinen
triftigen Grund dagegen gibt, sollte man die Indexschreibweise
bevorzugen.
Was in der Regel teuer ist, sind Pointer auf Pointer auf Pointer. Flache
Strukturen sind schneller.
Falk B. schrieb:> Weil du das Prinzip der Kapselung noch nicht verstanden hast. Eine> Funktion soll so weit wie möglich KEINERLEI unsichtbare Nebeneffekte> haben. Das erreicht man u.a. durch Funktionsparameter (welche Kopien> sind) und einem Rückgabeparameter. Es hat schon seinen Grund, warum es> in C normale Funktionsparameter (call by value) und Zeiger (call by> reference) gibt.
Naja was hindert dich daran die Übergabeparameter als const zu
deklarieren:
void foo(const int* const pointer1, const long* pointer2)
Damit stellst sicher, dass pointer1 nirgendwo hinzeigen kann und auch
dessen "Inhalt" nicht verändert werden kann...
Bei pointer2 hingegen kann der "Inhalt" geändert werden.
Nobody schrieb:> Damit stellst sicher, dass pointer1 nirgendwo hinzeigen kann und auch> dessen "Inhalt" nicht verändert werden kann...> Bei pointer2 hingegen kann der "Inhalt" geändert werden.
Pointer die nirgendwo hinzeigen sind sinnlos (außer NULL Pointer).
Außerdem wie definierst du Inhalt? Dein pointer1 ist ein konstanter
Pointer (das heißt es lässt sich nicht ändern wohin der Pointer zeigt)
auf einen konstanten Wert. Und pointer2 ist nur ein Pointer auf einen
konstanten Wert und ist damit ausreichend. Ob die Funktion das Ziel das
Pointers ändern kann ist egal, da die Funktion sowieso eine Kopie des
Pointers hat.