Hallo zusammen, ich frag mich das schon einige Zeit, doch mangels Sssemblerkenntnisen finde ich keine Antwort. Was mich interessiert sind Vor- und Nachteile von globalen Variablen bzw. Funktionsparametern. Ich dachte mir folgendes: Funktionsparameter haben den Vorteil, dass eine Funktion in sich "geschlossen" wird, und dadurch leicht von einem Projekt ins Andere kopiert werden kann. Dafür birgt sie den Nachteil (denk ich mir) dass der µC, auf dem das Programm dann läuft, ein paar mehr Befehle abzuarbeten hat, da er erst die Variablen an die richitgen stellen kopieren muss bevor er zur Funktion springt. Genau hier wäre der Vorteil einer globalen Variable. Alle Funktionen können direkt auf den gleichen Speicher zugreifen und der µC muss nicht immer vor jedem Aufruf die benötigten Daten rumkopieren. Auf kosten der portierbarkeit verteht sich. Ist das richtig so? oder ist das falsch? Oder wann bietet eine globale Variable Vorzüge gegenüber Funktionsparametern, wann sollte man mit Funktionsparametern arbeiten? vieln Dank Martin
Lass doch die Funktionen auch noch weg, dann stellt sich die Frage gar nicht mehr. Funktionen sind doch nur neumodischer Kram für Weicheier. Einfach alles hintereinander hinschreiben, in Künstlerkreisen uach Spagetticode genannt, dann klappt das schon. Oliver
Martin H. schrieb: > Ist das richtig so? oder ist das falsch? Bingo Auf einem kleinen µC kommt noch etwas dazu. globale Variable erlauben dir eine Abschätzung darüber, wieviel Speicher das Programm zur Laufzeit benötigen wird. > Oder wann bietet eine globale Variable Vorzüge gegenüber > Funktionsparametern, wann sollte man mit Funktionsparametern arbeiten? Bei Funktionen die * das Zeug haben, allgemein verwendbar zu sein * nur wenige Variablen (Parameter sind mir eher egal) zu benötigen bevorzuge ich in sich geschlossene Funktionen.
Martin H. schrieb: > Genau hier wäre der Vorteil einer globalen Variable. Alle Funktionen > können direkt auf den gleichen Speicher zugreifen und der µC muss nicht > immer vor jedem Aufruf die benötigten Daten rumkopieren. Bei AVR ist genau das Gegenteil der Fall: Globale Variablen sind langsam und teuer, da der AVR nicht im SRAM rechnen kann. Er muß alles erst in Register laden und danach wieder in den SRAM zurück schreiben. Er hat allerdings 32 Register. Übergibt man also Variablen als Funktionsargumente in den Registern, ist das codesparend und sauschnell. Peter
Martin H. schrieb: > Genau hier wäre der Vorteil einer globalen Variable. Alle Funktionen > können direkt auf den gleichen Speicher zugreifen und der µC muss nicht > immer vor jedem Aufruf die benötigten Daten rumkopieren. Das hängt sehr stark von der Prozessorarchitektur ab. Bei manchen sind statische Daten gut und effizient erreichbar, andere besitzen genug Register um Parameter (und lokale Daten) darüber wesentlich effizienter abzuwickeln als über statische Daten (z.B. AVR, ARM).
Globale Variablen haben noch den Nachteil, dass sie immer Speicher- platz belegen, Funktionsargumente und automatische lokale Variablen dagegen nur dann, wenn die betreffende Funktion auch tatsächlich aktiv ist. Globale Variablen, die nur von wenigen, selten aufgerufenen Funk- tionen verwendet werden, sind also oft verschenkter Speicherplatz. Man kann den GCC auch veranlassen, ausgewählte globale Variablen in Registern zu halten. Das bedeutet dann aber, dass diese Register während des gesamten Programmlaufs belegt sind und vom Compiler nicht anderwei- tig vergeben werden können. Setzt man dieses Feature unüberlegt ein, kehrt sich die erhoffte Effizienzsteigerung ins Gegenteil um.
Yalu X. schrieb: > Man kann den GCC auch veranlassen, ausgewählte globale Variablen in > Registern zu halten. Das bedeutet dann aber, dass diese Register während > des gesamten Programmlaufs belegt sind und vom Compiler nicht anderwei- > tig vergeben werden können. Setzt man dieses Feature unüberlegt ein, > kehrt sich die erhoffte Effizienzsteigerung ins Gegenteil um. Man muss hier aber auch noch erwähnen, dass dieses Feature gefährlich sein kann. Nämlich dann wenn man Library Funktionen benutzt und die Library nicht auf diese Spezialbelegung hin neu übersetzt wurde. Denn die Funktion wurden dann zu einem Zeitpunkt übersetzt, an denen der Compiler noch nicht wusste, dass er R17 (ich hab jetzt irgendein Register genommen nur um eine Zahl zu haben) nicht benutzen darf.
> wann sollte man mit Funktionsparametern arbeiten?
Solange wie möglich. Echte globale Variablen braucht man so gut wie nie,
Modul-globale Variablen (mit static Schlüsselwort) nur wenn unbedingt
notwendig. Ziehe es in Erwägung statt dessen mit Handles zu arbeiten.
Für Datenstrukturen ist dies oft erste Wahl.
PS: Wenn nicht unbedingt erforderlich lasse dich nicht von
Effizienzgedanken verführen (Stichwort "Premature optimization") - eine
vernünftige Strukturierung der Software ist besser.
Peter Dannegger schrieb: > Bei AVR ist genau das Gegenteil der Fall: > Globale Variablen sind langsam und teuer, da der AVR nicht im SRAM > rechnen kann. Ähm. Welcher Prozessor kann das denn? Ich meine direkt im Hauptspeicher rechnen? Auch ein x86 Prozzi holt doch die Daten erst mal in (E)AX etc. rein, bevor gerechnet wird.
Mark Brandis schrieb: > Welcher Prozessor kann das denn? Ich meine direkt im Hauptspeicher > rechnen? Auch ein x86 Prozzi holt doch die Daten erst mal in (E)AX etc. > rein, bevor gerechnet wird. Technisch geht es zwar immer durch die ALU, aber nicht immer durch Register. So kann auch x86 mit add mem, 2 ohne Verwendung eines sichtbaren Registers 2 zum Speicher dazuaddieren. Noch stärker ausgeprägt ist das beispielsweise beim MSP430, mit 2 möglichen Speicheroperanden im Befehl. AVR ist eine sogenannte registerorientierte "load-store" Architektur, d.h. es wird zwischen load/store Befehlen einerseits und registerbezogenen Rechenoperationen andererseits unterschieden. Von ein paar Ausnahmen abgesehen benötigen Operationen auf und mit dem Speicher folglich mehr Befehle als Operationen auf Register. Mit der Laufzeit der einzelnen(!) Operation hat das übrigens (meistens) nichts zu tun. Ob man load-increment-store explizit oder implizit in die Teiloperationen aufdröselt ist dafür wenig relevant. In einem Befehl ist es lediglich kürzer als in drei. Erst wenn man etliche benachbarten Befehle insgesamt betrachtet und etwas umsortiert erlaubt die Trennung eine in Summe höhere Leistung durch Überlappung ohne hohen Zusatzaufwand. Aber da sind wird in Gefilden jenseits der Controller wie AVR oder ARM7.
PS: Beim MIPS Core der PIC32 dürfte die erwähnte explizit programmierte Überlappung von Befehlen übrigens durchaus Nutzen bringen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.