Forum: Mikrocontroller und Digitale Elektronik Variablen >>> sauber Funktionsübergreifend


von __Son´s B. (bersison)


Lesenswert?

Hallo und guten Morgen.

ich stelle mir die Frage nach einem sauberen Programmierstil - Richtung 
C++.

Übungsannahme;
mehrere zusammengehörige Funktionen
SpgUeberwach_Initial()
SpgUeberwach_Auslesen()
SpgUeberwach_Mittelwert()
SpgUeberwach_Auswertung()
SpgUeberwach_Zuordnung()
die, durch gegenseitige Verschachtelungen, zum Teil auf die gleichen 
(static) Variablen zugreifen müssen.

Zur besseren/einfacheren, würde ich gerne alle zusammengehörigen 
Variablen in einer Funktion oder einen Block zusammenfassen. Bsp: 
SpgUeberwach_globalVariablen()
Somit hätte ich nicht den "Wust" von unübersichtlichen 
Übergabeparametern.

Geht das?
Ist das ein sauberer Programmierstil?

von Scelumbro (Gast)


Lesenswert?

Es fehlen viele Infos was du wirklich bezweckt, aber ich habe das Gefühl 
das es eine Klasse Spg_Ueberwach geben sollte welche die nötigen 
Variablen und die genannten Methoden (statisch) vorhält.

von __Son´s B. (bersison)


Lesenswert?

Scelumbro schrieb:
> Klasse Spg_Ueberwach geben sollte
Was ist eine "Klasse" innerhalb der Programmierung?

Mit SpgUeberwach_xxx ist eine Gruppe von Funktionen bezeichnet, die alle 
zusammen eine Spannungsüberwachung an einem oder mehreren Pins 
auswerten/verarbeiten.
Diese Gruppe (alle Funktionen SpgUeberwach_xxx) soll später in 
unterschiedlichen Programmen als Hintergrund laufen.
Damit bei Kopieren/Vererben dieser Hintergrundeigenschaft 
"Spannungsüberwachung" nichts vergessen wird, habe ich alles mit 
SpgUeberwach_ bezeichnet.

Jetzt geht es als letztes um einige Variablen und Definitionen, die 
gesammelt in einer Funktion/Modul (Bsp: SpgUeberwach_Parameter()) 
gesammelt werden.

von __Son´s B. (bersison)


Lesenswert?

Es geht um globale Variable.
Bilden die einen sauberen Programmierstil, oder eher für den "Notfall"?
Kann man die, aus optischen Zugehörigkeits-Gründen, irgend wie in einer 
Gruppe oder einer Funktion zusammen fassen?

von Dieter (Gast)


Lesenswert?

Du möchtest in Richtung C++ und fragst was Klassen sind. Nicht dein 
ernst. Hast Du einmal den Suchbegriff C++ eingegeben?

von icke (Gast)


Lesenswert?

Struct?

von Rolf M. (rmagnus)


Lesenswert?

__Son´s B. schrieb:
> Scelumbro schrieb:
>> Klasse Spg_Ueberwach geben sollte
> Was ist eine "Klasse" innerhalb der Programmierung?

Einer der wichtigsten Teile von C++. Und das, was du da beschreibst, 
klingt exakt nach dem, wofür man in C++ eine Klasse machen würde.

von __Son´s B. (bersison)


Lesenswert?

Dieter schrieb:
> Du möchtest in Richtung C++ und fragst was Klassen sind. Nicht dein
> ernst. Hast Du einmal den Suchbegriff C++ eingegeben?

Mir geht es, wie beschrieben, um kleine/modulare Einheiten mit festen 
Zuordnungen!
"Richtung" bedeutet; einige Elemente und Orientierungen. Dazu muss nicht 
C++ in Gänze beherrscht werden ;-)
Weiter Baustellen kann ich mir derzeit nicht leisten!

von __Son´s B. (bersison)


Lesenswert?

Rolf M. schrieb:
> Einer der wichtigsten Teile von C++. Und das, was du da beschreibst,
> klingt exakt nach dem, wofür man in C++ eine Klasse machen würde.

Ok! Dann werde ich mich doch mit "Klasse"n beschäftigen.

von Falk B. (falk)


Lesenswert?

@ __Son´s Bersi__ (bersison)

>"Richtung" bedeutet; einige Elemente und Orientierungen. Dazu muss nicht
>C++ in Gänze beherrscht werden ;-)
>Weiter Baustellen kann ich mir derzeit nicht leisten!

Gute Idee.

>Ok! Dann werde ich mich doch mit "Klasse"n beschäftigen.

Keine gute Idee!

>Es geht um globale Variable.
>Bilden die einen sauberen Programmierstil, oder eher für den "Notfall"?

Eher Notfall. Nach Möglichkeit nutzt man immer Funktionsparameter. 
Werden die zu viele, packt man die Daten zusammen in ein Struct und 
übergibt einen Pointer darauf. Auch das geht ohne globale Variablen.

>Kann man die, aus optischen Zugehörigkeits-Gründen, irgend wie in einer
>Gruppe oder einer Funktion zusammen fassen?

Wie schon erwähnt, mit einem Struct.

Lern erstmal ordentlich die Grundlagen in C, dann kannst du über echtes 
C++ nachdenken. Bis dahin hast du mit C viel zu tun und auch ausreichend 
Möglichkeiten zur

Strukturierte Programmierung auf Mikrocontrollern

Siehe auch

Strukturen in C

Kauf dir ein ordentlichen C-Grundlagenbuch und arbeite das systematisch 
und komplett durch! Alles andere ist nur Gemurkse.

von Noch einer (Gast)


Lesenswert?

Tja, da gibt es halt zwei Ansichten.

Die einen meinen, so etwas wie die stdio.h war optimal. Nach außen sind 
nur FILE* und die Funktionen bekannt. Alle internen Variablen bekommt 
der Anwendungsprogrammierer niemals zu sehen.

Andere meinen, was C da bietet sei nicht elegant genug. Es erfordert so 
viele Tricks, dass wir besser die Klassen aus C++ benutzen.

Musst halt beides selbst ausprobieren.

von Jojo S. (Gast)


Lesenswert?

Der 'Trick' den C++ bei den Methoden einer Klasse nutzt ist der (im 
Aufruf unsichtbare) Zeiger auf sich selber, 'this'. Das kann man wie 
Falk auch gerade schrieb selber bauen und das wird auch häufig so 
gemacht.
Du packst deine Parameter und Arbeitsvariablen in eine Struktur und jede 
Funktion bekommt als erstes Argument einen Zeiger auf eine Variable mit 
dieser Struktur. Auf diese Weise kannst du mehrere 'SpgUeberwach' 
Instanzen (durch die Variablen mit SPGUEBERWACH_TYPE Struktur) anlegen 
ohne globale Variablen.

von Daniel A. (daniel-a)


Lesenswert?

@Jojo S. (jojos)

Das habe ich in folgendem Beitrag mal veranschaulicht:
Beitrag "Re: This Pointer"

@__Son´s Bersi__ (bersison)
Du hast soweit ich dass sehe noch garnicht erwähnt, ob du C++ oder eine 
andere Sprache nutzt. Oder planst du mit C++ anzufangen (richtung c++ 
ist sehr unspezifisch). Das Problem mit C++ sind die vielen 
Möglichkeiten etwas umzusetzen, man muss aufpassen es mit den 
Sprachfeatures nicht zu verlieren.

von Hans (Gast)


Lesenswert?

Was Du suchst ist ein struct. Ein struct ist einfach eine Sammlung von 
zusammengehörigen Variablen. Den Funktionen, die damit arbeiten sollen, 
übergibst Du einen Zeiger auf die Struktur.
1
// spgueberwach.h
2
3
struct SpgUeberwach
4
{
5
  int           wert;
6
  unsigned char nochEineVariable;
7
}
8
9
void SpgUeberwach_Initial(struct SpgUeberwach* spgu);
10
int  SpgUeberwach_Auslesen(const struct SpgUeberwach* spgu);
11
void SpgUeberwach_Zuordnung(struct SpgUeberwach* spgu, int wert)
1
// spgueberwach.c
2
3
#include "spgueberwach.h"
4
5
void SpgUeberwach_Initial(struct SpgUeberwach* spgu)
6
{
7
  spgu->wert = 0;
8
  spgu->nochEineVariable = 0;
9
}
10
11
int SpgUeberwach_Auslesen(const struct SpgUeberwach* spgu)
12
{
13
  return spgu->wert;
14
}
15
16
void SpgUeberwach_Zuordnung(struct SpgUeberwach* spgu, int wert)
17
{
18
  spgu->wert = wert;
19
}
1
// main.c
2
3
#include "spgueberwach.h"
4
#include <stdio.h>
5
6
void main(void)
7
{
8
  struct SpgUberwach meinSpgu;
9
  SpgUeberwach_Initial(&meinSpgu);
10
  SpgUeberwach_Zuordnung(&meinSpgu, 5);
11
  printf("Wert: %d\n", SpgUeberwach_Auslesen(&meinSpgu));
12
}

In C++ kann man das syntaktisch kürzer hinschreiben, es ergibt aber 
unterm Blech genau den gleichen Code.
1
// spgueberwach.h
2
3
class SpgUeberwach
4
{
5
  public:
6
    SpgUeberwach(); // Konstruktor
7
    int auslesen() const;
8
    void zuordnung(int wert);
9
10
  private:
11
    int           mWert;
12
    unsigned char mNochEineVariable;
13
}
1
// spgueberwach.cpp
2
3
#include "spgueberwach.h"
4
5
SpgUeberwach::SpgUeberwach()
6
  : mWert(0)
7
  , mNochEineVariable(0)
8
{
9
}
10
11
int SpgUeberwach::auslesen() const
12
{
13
  return mWert;
14
}
15
16
void SpgUeberwach::zuordnung(int wert)
17
{
18
  mWert = wert;
19
}
1
// main.cpp
2
3
#include "spgueberwach.h"
4
#include <iostream>
5
6
void main(void)
7
{
8
  SpgUberwach meinSpgu; // Konstruktor wird automatisch aufgerufen
9
  meinSpgu.zuordnung(5);
10
  std::cout << "Wert: " << meinSpgu.auslesen() << std::endl;
11
}

Es ist übrigens üblich, Funktionen so zu benennen, dass sie mit einem 
Verb anfangen. Funktionen, die nur einen Wert in der Struktur/Klasse 
lesen/schreiben nennt man Getter/Setter, also beispielsweise 
SpgUeberwach_SetzeWert statt SpgUeberwach_Zuordnung, wenn die Namen 
unbedingt Deutsch sein sollen. Aus meiner Sicht ist lesbarer, 
durchgängig englische Namen zu verwenden, aber das ist ja hier nicht 
Thema ...

von Rolf M. (rmagnus)


Lesenswert?

Falk B. schrieb:
>>Ok! Dann werde ich mich doch mit "Klasse"n beschäftigen.
>
> Keine gute Idee!

Du meinst, wenn er C++ lernen will, ist es besser, es erstmal so zu 
machen, wie man es in C++ eigentlich nicht macht, um dann später 
irgendwann zu lernen, wie's richtig geht.

> Lern erstmal ordentlich die Grundlagen in C, dann kannst du über echtes
> C++ nachdenken.

ok, dann aber bitte bewusst C lernen und nicht ein pseudo-C++.

von __Son´s B. (bersison)


Lesenswert?

Ok, dank euch erst einmal für die vielen Anregungen!
Jetzt werde ich die Anregungen erst einmal sacken lassen und 
verarbeiten.

Wenn ein sauberer, struktureller, übersichtlicher Programmcode raus 
kommt, werde ich bei C bleiben - hier befinden sich schon genug 
Baustellen.
_____________________________________________
Vor Jahrzehnten hatte ich mich nach Basic, Fortran77, C, mit C++ 
beschäftigt und deren OOP-Logik bestechend erachtet. Ist aber alles(!) 
verschütt gegangen - somit fange ich gerade wieder neu und klein an.
_____________________________________________

von Peter D. (peda)


Lesenswert?

Die saubere Lösung ist, daß es keine globalen Variablen gibt.
Variablen bleiben immer Objekt-lokal (static).
Müssen andere Objekte darauf zugreifen, gibt es dafür entsprechende 
Funktionen.

Ob man eine Struct anlegt, hängt davon ab, ob diese Struct mehrfach 
benötigt wird oder Struct-Pointer verwendet werden sollen.

von Noch einer (Gast)


Lesenswert?

... und als kleine Ergänzung.

Man kommt mit reinem C schon recht weit, wenn für jedes "Objekt" eine 
*.c Datei und eine *.h Datei anlegt. In der *.h Datei nur möglichst 
wenige Struct-Pointer und möglichst wenig Funktionen bekannt machen.

Bevor du eine Variable in der *.h bekannt machst, 3 mal überlegen, ob es 
auch anders geht.

von Sascha (Gast)


Lesenswert?

__Son´s B. schrieb:
> Es geht um globale Variable.
> Bilden die einen sauberen Programmierstil, oder eher für den "Notfall"?
> Kann man die, aus optischen Zugehörigkeits-Gründen, irgend wie in einer
> Gruppe oder einer Funktion zusammen fassen?

Da musst du jetzt mal ein Buch über objektorienterte Programmierung 
lesen.

Kurz und knapp: Globale Variablen werden dabei eher vermieden, haben 
aber immer noch ihre Daseinsberechtigung.

von Jojo S. (Gast)


Lesenswert?

Hans schrieb:
> struct SpgUeberwach
> {
>   int           wert;
>   unsigned char nochEineVariable;
> }

Sehr fleissig das ganze Beispiel zu liefern.
Es lohnt sich noch einen Typen SPG_TYPE zu definieren, das reduziert die 
Schreibarbeit:
1
typedef struct {
2
  int           wert;
3
  unsigned char nochEineVariable;
4
} SPG_TYPE;
5
6
SPG_TYPE spg1;
7
SPG_TYPE spg2;
8
9
void SpgUeberwach_Initial(SPG_TYPE* spgu)

von Sven B. (scummos)


Lesenswert?

Falk B. schrieb:
> Kauf dir ein ordentlichen C-Grundlagenbuch und arbeite das systematisch
> und komplett durch! Alles andere ist nur Gemurkse.

"erstmal C lernen" wenn man C++ programmieren will ist meines Erachtens 
eine blöde Idee. C++ ist völlig anders als C, der Programmierstil ist 
völlig unterschiedlich, und Menschen die gut C können schreiben oft sehr 
merkwürdiges C++.

von __Son´s B. (bersison)


Lesenswert?

Ich werde bei C bleiben!
Da ich damit angefangen habe und mir entsprechende Fachliteratur und 
uC-Versuchsanordnungen vor liegen.
Durch struct bin ich doch schon da, wo ich hin will.

von Falk B. (falk)


Lesenswert?

Amen!

von __Son´s B. (bersison)


Lesenswert?

ahhhh - noch eine Frage zum sauberen Code-Stil.

Folgend 2 mögliche main()-Module in unterschedlicher Übersichtlichkeit 
vs. Kompaktheit.
____________________________________________
// --1-- übersichtlicher (finde ich), aber mit 2 zusätzlichen Variablen
uint16_t Mittelwert;
uint8_t StatusNeu;

MittelWert = SpgUeberwach_Mittelwert(100,0);
StatusNeu = SpgUeberwach_Auswertung(MittelWert);
SpgUeberwach_Ausgang(StatusNeu);
____________________________________________
//--2-- sehr kompakt
SpgUeberwach_Ausgang(SpgUeberwach_Auswertung(SpgUeberwach_Mittelwert(100 
,0)));
____________________________________________

Alle weitern Codes sind gleich.
Bei der Spannungsüberwachung handelt es sich um einen Teil des gesamten 
uC-Prog.

von Jojo S. (Gast)


Lesenswert?

V1 ist übersichtlicher, die würde ich bevorzugen. Der Compiler optimiert 
das sowieso, da braucht man sich keine Gedanken über zuviel 
Resourcenverschwendung zu machen. Und es ist leichter zu debuggen wenn 
Zwischenergebnisse in Variablen auftauchen.

von __Son´s B. (bersison)


Lesenswert?

DANKE!

von EFA (Gast)


Lesenswert?

V1.

Lesbarkeit/Maintainability/Robustness sind wichtiger, als Sourcezeilen 
oder ein bissel Laufzeit zu sparen. Die Zeiten, in denen man in 
Assembler aufs letzte Byte optimieren mmusste sind vorbei.

Und nochmal zu der Ursprungsfrage: Globale Variablen braucht man nicht. 
Nie. Und wenn doch läuft etwas schief.

von __Son´s B. (bersison)


Lesenswert?

EFA schrieb:
> Und nochmal zu der Ursprungsfrage: Globale Variablen braucht man nicht.
> Nie. Und wenn doch läuft etwas schief.

Ja, ist an gekommen.
Trotzdem wird es einen kompakten Bereich geben in dem ich einmalig alle 
Grundparameter ablege. Habe es gerade mit Präproz-Makros gelöst.
Mit struct() bin ich aus Zeitmangel noch nicht weiter gekommen.

von Falk B. (falk)


Lesenswert?

@ EFA (Gast)


>Lesbarkeit/Maintainability/Robustness sind wichtiger, als Sourcezeilen
>oder ein bissel Laufzeit zu sparen. Die Zeiten, in denen man in
>Assembler aufs letzte Byte optimieren mmusste sind vorbei.

Stimmt.

>Und nochmal zu der Ursprungsfrage: Globale Variablen braucht man nicht.
>Nie. Und wenn doch läuft etwas schief.

Ist mir zu dogmatisch. Theoretisch mag das funktionieren, PRAKTISCH sind 
globale Variablen MINDESTENS für ISR-Main Kommunikation nötig, da geht 
es gar nicht anders. Ausserdem kann man bei KLEINEN Programmen mit 
SINNVOLLEN globalen Variablen die Übergabe von zuviel Parametern 
zwischen Funktionen sparen. Wenn es um das Thema Multitasking in seinen 
verschiedenen Ausprägungen geht, sind globale Variablen auch sehr 
nützlich. Man darf es nur nicht übertreiben, weder in die eine noch 
ander Richtung!

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.