Guten Abend liebe Programmierer
Ich habe eine Frage bezüglich einer sauberen Programmierstruktur.
Mittlerweile ist mein Programm relativ gross und ich bemühe mich um
einen sturkturierten und sauberen Aufbau.
Wie ist eure Meinung zu globalen Variabeln in einem C Programm? Versucht
ihr sie eher zu vermeiden, indem ihr mit mehreren return-Anweisungen
arbeitet oder sind eure Programme voll mit globalen Variablen?
Gruss
Kommt drauf an.
Auf einem PC, auf dem du genügend Speicher hast, so dass du kein Auge
auf dem zur verfügung stehenden Speicher werfen musst, sind globale
Variablen genau das, was du nicht willst.
Auf einem kleinen µC, wie den AVR sieht die Sache anders aus. Hier ist
die SRAM Größe stark beschränkt, so dass es lebenswichtig ist
* den Stack durch nicht zuviele Funktionsargumente zu belasten
* den Überblick über den momentanen SRAM Verbrauch zu behalten
beides erfordert gloable Variablen, weil nur so die SRAM Statistik
ausreichend aussagekräftig ist. Gegen kurze Funktionen mit wenig eigenem
Stack-Verbrauch ist trotzdem nichts einzuwenden, aber zumindest die
Stammdaten macht man dann als globale Variablen und nicht als Variablen
in main(), die man an Funktionen weitergibt.
> indem ihr mit mehreren return-Anweisungen
return hat allerdings damit nur in Ausnahmefällen zu tun. Wenn eine
Funktion einen Wert errechnet, dann spricht nichts dagegen, den aus der
FUnktion heruas zu returnieren. An dieser Stelle statt dessen globale
Variablen einzusetzen wäre 'strange'. (Arrays sind wie immer die große
Ausnahme. Aber ausser Stringverarbeitung hat man das selten auf einem
µC)
Chris S. schrieb:> Guten Abend liebe Programmierer>> Ich habe eine Frage bezüglich einer sauberen Programmierstruktur.> Mittlerweile ist mein Programm relativ gross und ich bemühe mich um> einen sturkturierten und sauberen Aufbau.
Das ist auf jeden Fall schon mal gut!
> Wie ist eure Meinung zu globalen Variabeln in einem C Programm? Versucht> ihr sie eher zu vermeiden, indem ihr mit mehreren return-Anweisungen> arbeitet oder sind eure Programme voll mit globalen Variablen?
Globale Variablen sind unter Entwicklern nicht gern gesehen, sind
unschön.
Das kommt daher, das wirklich globale Variablen (also in Header
global.h, welcher überall inkludiert wird) von überall verändert werden
können, und dann schnell mal der Überblick verloren geht wer wann
zugreift und warum.
Wenn ich Mikrocontroller in C Programmiere, habe ich aber auch viele
Globale Variablen, ich deklariere die aber immer in einem C File (nie in
einem Header file), so, dass diese nur innerhalb des einen Files
sichtbar sind. ("privat")
Somit habe ich in einem File zusammenhängende Funktionen, und verliere
nicht den Überblick über die Zugriffe.
Meine persönliche Meinung bei der Mikrocontroller Entwicklung. Bei der
Entwicklung von PC Applikationen, egal in welcher Sprache, vermeide ich
globale Variablen wenn möglich. (Da entwickle ich aber auch
Objektorientiert...)
mfg Andreas
> indem ihr mit mehreren return-Anweisungen arbeitet> oder sind eure Programme voll mit globalen Variablen
Was hat das eine mit dem anderen zu tun ?
Glaubst du
1
intf(inti)
2
{
3
i=i+1;
4
return4+i;
5
return5+i;
6
return6+i;
7
}
funktioniert und wäre vergleichbar mit
1
inta,b,c;
2
3
voidf(inti)
4
{
5
i=i+1;
6
a=4+i;
7
b=5+i;
8
c=6+i;
9
}
Kann ja nicht sein. Funktioniert auch nicht, return 5+i wird nie
ausgeführt.
Ein C++ Programmierer legt für ein Programm eine Klasse an,
von der es eine Instanz im Prozess gibt,
und bringt in der Klasse Membervariablen unter,
die von Methoden als Seiteneffekt modifiziert werden
(das ist auch einfach und eenig Tipparbeit,
weil man nur den Variablennamen nenne muss)
wodurch sich der Zustand des Objektes ändert.
Globale Variablen in normalen C sind Membervariablen vom Prozess.
Wenn Funktionen diese als Seiteneffekt ändern, ändern sie den
Prozesszustand.
Das ist funktionell nichts anderes, nur effizienter.
Dennoch sind globale Variablen verschrieen,
von den Leuten, die nichts verstanden haben.
Man sollte den Rückgabewert einer Funktion mit return liefern,
hat sie mehrere Rückgabewerte sollten Parameter auf Variablen
zeigen in denen die Werte abgelegt werden sollen,
und hat man viele Rückgabewerte sollte eine Struktur ausgefüllt
werden.
Geht es jedoch nicht um Rückgabewerte, sondern um Änderung des
Zustandes des Programms, sind globale Variablen vollkommen in
Ordnung.
Man muß sich nur klar werden, daß man nur einen Zustand hat.
Ein Umkpoieren von Werten aus globalen Variablen nach einem
Funktionsaufruf in andere Variablen ist fast immer ein Zeichen,
daß man den Unterschied in der empfohlenen Anwendung zwischen
globaler Variable und return nicht verstanden hat.
MaWin schrieb:> Dennoch sind globale Variablen verschrieen,> von den Leuten, die nichts verstanden haben.
Nicht von Leuten die nichts verstanden haben.
Sondern von Leuten die Software ein paar Nummern größer schreiben als du
das gewohnt bist.
MaWin ich habs dir schon einmal gesagt.
Du bist ein Spitzenmann wenn es um Hardware geht.
Aber von Software hast du nur einen ganz kleinen SChimmer.
Nimm dich nicht als Massstab dafür, was vernünftiges Softwaredesign ist.
Mit Leuten, die Ansichten wie du haben,, hab ich jeden Tag zu tun. Und
ich (und nicht nur ich) würde sie am liebsten jeden Tag 2 mal auf den
Mond schiessen.
Wenn der Aufrufer mit dem Ergebnis weiter arbeiten soll, ist ein
Returnwert vorzuziehen.
Sind mehrere Werte zurück zu geben, kann man eine Struct als Returntyp
definieren.
Das ergibt nebenbei auch schnelleren, kürzeren Code und weniger
RAM-Verbauch, da der Wert in Registern übergeben werden kann.
Chris S. schrieb:> Wie ist eure Meinung zu globalen Variabeln in einem C Programm?
Ich schätze, du verwechselst da was. Wahrscheinlich meinst du den
Unterschied zwischen Variablen, die statisch im RAM angeordnet werden
(das sind alle, die du außerhalb von Funktionen/Prozeduren anlegst) und
solchen, die nur innerhalb eines Unterprogramms deklariert und benutzt
werden und die deshalb auf dem Stack angelegt werden.
Mach dir einfach die simple Regel zueigen, daß man nur das als Argument
einer Funktion übergibt, was bei verschiedenen Aufrufen dieser Funktion
auch tatsächlich unterschiedlich sein kann. Argumente, die immer wieder
die gleichen sind, sind albern und machen nicht nur mehr Streß, sondern
blähen auch den Code auf.
Ansonsten entscheide einfach selber nach deinem (hoffentlich
qualifizierten) Gutdünken, welche Variablen du dem Stack zumuten willst
und welche du lieber statisch im RAM haben willst.
Alle solche Sprüche wie "Globale Variablen auf das absolut notwendige
Minimum beschränken!" kannst du getrost in den Skat drücken. Wer so
generalisiert, hat mit Sicherheit keinen wirklichen Überblick und
wiederholt nur Sprüche seines Lehrers von anno Toback.
Gleiches gilt übrigens auch für "goto ist Spaghetticode und ist deshalb
strikt zu vermeiden!" Wie sind doch ganze Generationen von
C-Hasenschülern auf solche Sprüche dressiert worden, bloß weil 'goto' im
Basic der 80er Jahre ne Notwendigkeit war und alle Homecomputer-Kinder,
die mal Programmierer werden wollten, eben Basic verinnerlicht hatten
und mit Prügeln zu C hin umdressiert werden mußten.
W.S.
> > Dennoch sind globale Variablen verschrieen,> > von den Leuten, die nichts verstanden haben.> Nicht von Leuten die nichts verstanden haben.
Doch, genau von denen, wie du es gerade bestätigt hast.
> Aber von Software hast du nur einen ganz kleinen SChimmer.
Du hast schon Betriebssysteme geschrieben ?
Du hast schon Compiler geschrieben ?
Du hast schon Textverarbeitungsprogramme geschrieben ?
Du hast schon Chart-Graphik-Programme geschrieben.
Du hast schon Spiele geschrieben.
Du hast schon Windows Applikationen geschrieben.
Du hast schon Smartphone-Applikationen geschrieben.
Du hast schon Flugnavigationssoftware geschrieben.
Du hast schon GUIs geschrieben (also Window Manager und GDI)
Du hast schon Mathematik-Libraries geschrieben (Cordic & co.)
Du hast schon Statistik-Libraries geschrieben.
Du hast schon Druck-Postprozessing geschrieben.
Du hast schon Gerätetreiber geschrieben.
Du hast schon Interpreter und Debugger geschrieben.
Warum nur glaube ich das nicht. Ganz einfach, weil deine Aussagen
so typisch sind für jemanden, der das alles noch nie getan hat.
MaWin schrieb:>> > Dennoch sind globale Variablen verschrieen,>> > von den Leuten, die nichts verstanden haben.>> Nicht von Leuten die nichts verstanden haben.>> Doch, genau von denen, wie du es gerade bestätigt hast.>>> Aber von Software hast du nur einen ganz kleinen SChimmer.
Jeder der schon mal versucht hat ein Programm zur Optimierung
Multithreadet zu machen, stolpert früher oder später über globale
Variablen. Denn auf einmal hat das Programm nicht mehr nur einen Status
sondern mehre gleichzeitig.
Wenn sie const sind, kann man sie verwenden, aber im Normalfall sind sie
zu vermeiden auch wenn du davon nicht überzeugt bist.
> Jeder der schon mal versucht hat ein Programm zur Optimierung> Multithreadet zu machen, stolpert früher oder später über globale> Variablen.
Dann schubst man die globalen Variablen als Members in eine
Prozess-Klasse, alle Funktionen die auf diesen Variablen
arbeiten als Methoden auch dahinein,
und hat mit self einen Bezug auf den aktuellen Thread.
Das ist kein Problem, und kein Grund, ein Programm, welches
NICHT multithreaded ist und es mit 99.99%iger Sicherheit
niemals werden wird, mit dem Ballast eben dieser Klasse
(indirekter Zugriff auf Member und zusätzlicher Parameter
bei Mathoden) zu belasten.
Diesen Zusammenhang (global = members des Prozesses) hatte ich
oben schon beschrieben, du hast es offenbar übersehen.
Peter II schrieb:> MaWin schrieb:>>> > Dennoch sind globale Variablen verschrieen,>>> > von den Leuten, die nichts verstanden haben.>>> Nicht von Leuten die nichts verstanden haben.>>>> Doch, genau von denen, wie du es gerade bestätigt hast.>>>>> Aber von Software hast du nur einen ganz kleinen SChimmer.>> Jeder der schon mal versucht hat ein Programm zur Optimierung> Multithreadet zu machen, stolpert früher oder später über globale> Variablen. Denn auf einmal hat das Programm nicht mehr nur einen Status> sondern mehre gleichzeitig.
Nicht unbedingt. Oder man muss das Programm genauer eingrenzen.
Jeder von uns, der (Mikro)Prozessoren programmiert, arbeitet permanent
mit globalen Variablen und findet das auch völlig legitim - egal ob
multithreaded oder gar auf mehreren Kernen.
Als solche globalen Variablen treten beispielsweise die SFRs des
Prozessors in den C-Sprachraum. Die beschreiben im einfachsten Sinne
nämlich genau den von MaWin erwähnten Zustand des 'Programms'.
Und schließlich wird eine Variable nicht weniger global, nur weil man
sie hinter Singletons o.ä. versteckt. Das mag den Zugriffsmechanismus
regeln (zum Beispiel mit einer Verriegelung bei multithreaded), aber
global ist die Variable zumindest semantisch immer noch. Und das ist ja
auch in Ordnung so.
MaWin schrieb:> Das ist kein Problem, und kein Grund, ein Programm, welches> NICHT multithreaded ist und es mit 99.99%iger Sicherheit> niemals werden wird, mit dem Ballast eben dieser Klasse> (indirekter Zugriff auf Member und zusätzlicher Parameter> bei Mathoden) zu belasten.
Du solltest als Hellseher auftreten, ich kann von meinen Programm nie
mit 99% Sicherheit sagen wie sie sich in Zukunft entwickeln werden.
Übrigens gibt es ausreichend libs wie z.b. libpng die das scheinbar auch
gedacht haben. Sobald man sie in einen Multitheaded Programm verwendet
knallt ist. (keine Ahnung ob die aktuell Version noch betroffen ist)
Lieber gleich richtig machen, als später umbauen.
MaWin schrieb:> Du hast schon Compiler geschrieben ?> Du hast schon Textverarbeitungsprogramme geschrieben ?> Du hast schon Chart-Graphik-Programme geschrieben.> Du hast schon Spiele geschrieben.> Du hast schon Windows Applikationen geschrieben.> Du hast schon Smartphone-Applikationen geschrieben.> Du hast schon GUIs geschrieben (also Window Manager und GDI)> Du hast schon Mathematik-Libraries geschrieben (Cordic & co.)> Du hast schon Gerätetreiber geschrieben.> Du hast schon Interpreter und Debugger geschrieben.
Jep. Fuer die paar, die ich streichen musste, habe ich Ersatz, zum
Beispiel Filesysteme, diverse Plugins, etc. Wie viele Treffer auf deiner
Liste kannst du verzeichnen?
Zur Sache hat Karl Heinz mal wieder Recht - du nicht.
MaWin schrieb:> Du hast schon Betriebssysteme geschrieben ? [...]
All das kann man so oder so machen, mit mehr oder weniger Erfolg... Nur
weil man etwas irgendwie mal programmiert hat muss das nicht
notwendigerweise gut gewesen sein.
Besonders in Industrie-und Nischenanwendungen trifft man auf viel hoch
gelobte & als der Weisheit letzter Schluss deklarierte Software die dann
doch ziemliche Sch**e ist.
> Du solltest als Hellseher auftreten, ich kann von meinen Programm nie> mit 99% Sicherheit sagen wie sie sich in Zukunft entwickeln werden.
Aber du baust schon alles ein damit es alle möglichen vielleicht mal
nötigen Änderungen "vorbereitet" hat.
Du bist der Hellseher.
Die am schlechtesten wartbaren Programme sind übrigens solche
Käse-Schinken, die haufenweise derzeit nutzlosen code enthalten.
Ausserdem ist dein Programm damit teurer als nötig (oder schlechter zum
selben Preis) weil du dich mit Arbeiten beschäftigst, die der Kunde gar
nicht bestellt hat.
> Wie viele Treffer auf deiner Liste kannst du verzeichnen?
Alle. Und natürlich enthält ein Betriebssystem ein Filesystem und
natürlich schreibt man Plugins, beispielsweise Importfilter.
> Nur weil man etwas irgendwie mal programmiert hat muss das nicht> notwendigerweise gut gewesen sein.
Egal wie man es gemacht hat, man hat daraus gelernt, und wie ich an
euren Beiträgen sehe, habt ihr noch nichts gelernt. Bei den allermeisten
vermisse ich sogar den selbstverständlichen Grundlagenstand eines
entsprechenden Studiums.
MaWin schrieb:> habt ihr noch nichts gelernt.
Doch, allerdings unterscheidet sich der erzielte Lerneffekt der meisten
von uns offenbar diametral von deinem. Das ist dann ein bisschen wie
mit dem Falschfahrer auf der Autobahn … „Was, einer? Alle!“
> Das ist dann ein bisschen wie mit dem Falschfahrer auf der Autobahn> … „Was, einer? Alle!“
Ganz einfach Jörg: Guck auf die Schilder, in diesem Fall das was dir in
der Informatik-Vorlesung erzählt wurde (falls du so was überhaupt mal
mitbekommen hast, klingt eher nicht danach).
Du (weiss ich gar nicht, hab's bisher nur von anderen gelesen) wollen
sich einfach ihre lasche Arbeitsweise und miesen Ergebnisse schönreden
und als angeblichen Stand der Technik (damit haben sie teilweise Recht,
fehlerhafte fette Programme sind leider üblich) als ausreichend
hinlügen.
Klar, meine Programme sind auch nicht optimal, aber wenigstens weiß ich
das und rede es nicht schön, und vor allem: Ich schreibe nicht
absichtlich unoptimalen Code und erfinde für die falsche Richtung jede
Menge Ausreden.
MaWin schrieb:> Du (weiss ich gar nicht, hab's bisher nur von anderen gelesen) wollen> sich einfach ihre lasche Arbeitsweise und miesen Ergebnisse schönreden
Komisch. Genau diesen Eindruck haben wir alle von dir …
Jörg Wunsch schrieb:> Komisch. Genau diesen Eindruck haben wir alle von dir
Du machst dich lächerlich, und du weisst es bereits selber,
holst du doch "wir alle" die imaginäre Masse zum
vermeintlichen Schutz hinter dich.
Auch bist du wirklich auf Kindergartenniveau, einfallslos
einfach "dasselbe" vom Gegenüber zu behaupten.
Ich wäre dann ein Teil von Jörgs imaginärer Masse.
Und dass man ein Betriebssystem programmiert hat, sagt noch nicht, dass
man in allen Fragen Recht hat (Wie beispielsweiße der gute Andre
Tannenbaum feststellen musste: Irgendwie ist dieses total veraltete
Linux immernoch nicht tot, obwohl Minix doch so viel besser ist)
Und ja, manchmal machen globale Variablen auch am PC sinn. Das sind aber
eher ausnahmen, meistens kann man mit einem Bisschen Zusatzaufwand eine
mindestens gleichwertige Lösung finden, die, falls das Programm
weiterentwickelt werden soll, weniger Probleme bereitet. Auf nem µC
empfielt sich in dem Zusammenhang noch das Schlüsselwörtchen static für
globale Variablem, damit prüft dann der Compiler gleich mit, dass sie
nur in ihrer Übersetzungseinheit verwendet werden.
Was MaWins Unoptimiertheit von Code ohne Globale Variablen angeht:
1) Voreilige Optimierungen haben meist gegenteiligen Effekt. Falls es da
Verbesserungen zu holen gibt, wird der Compiler einen guten Teil davon
schon rausholen.
2) Spätestens, wenn Caches ins Spiel kommen, ist der Vorteil weg, weil
die Variablen entweder dauerhaft im Cache gehalten werden müssen (und
damit den Cache verschwendet) oder aber doch dann, wenn sie gebraucht
wird einfach mitübergeben wird. Und damit wäre es doppelter Aufwand.
Gleiches trifft auf GOTO zu: Es hat offensichtlich eine Verwendung,
sonst wäre es nicht in C und dann auch noch in C++ gelandet. Man kann
zum Beispiel Pseudo-Exceptions auf nem µC in C damit realisieren. Oder
Informatiklehrer (und sich selbst) in die Verzweiflung treiben. Aber:
Auch wenn die Verwendung sinnvoll sein kann - In 99.9% der Fälle ist sie
es eben nicht, sondern ein Ausdruck dessen, dass da am Gesammtkonzept
was nicht stimmt.
Falls Chris S. noch spezifische Fragen hat möge er bitte einen neue
Thread eröffnen, hier kommt denke ich nichts mehr rum was mit dem
ursprünglichem Thema zu tun hätte.