Forum: Compiler & IDEs globale variablen vs. Funktionsparameter


von Martin H. (Gast)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von dr.no (Gast)


Lesenswert?

> 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.

von Mark B. (markbrandis)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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
Noch kein Account? Hier anmelden.