Forum: Compiler & IDEs Anfängerhilfe bei static Variablen


von Hans Melten (Gast)


Lesenswert?

Hallo,

ich bin blutiger Anfänger in C und schreibe derweil an einem Programm 
für eine Nixie Uhr als "Aufbaukurs".

In meiner ersten Version des Programmes war alles in ein main-File 
gestopft.
Das wollte ich nun abändern und habe mich an ein neues Programm gesetzt, 
wo ich jede Funktion in sein eigenes .c File schreibe, damit ich später 
auch mal etwas umfangreiche Programme schreiben kann.

Da es sich ja um eine Uhr handelt habe ich 3 Variablen stunden, minuten 
und sekunden. Diese habe ich dann als static gesetzt (global geht ja nur 
in einem .c File ?), da ich mehrere "ausgelagerte" Funktionen in .c 
Files habe die die Uhrzeit-Variablen verändern bzw. benutzen ( 
Uhrzeitstellen, eine Interruptroutine und die Ausgabefunktion ). Da ich 
die Variablen in Headerfiles drin hab, meckert das AVR-Studio nun 
andauernd über deklarierte aber nicht benutzte Variablen in main.

Jetzt meine Frage : Gibt es noch eine andere möglichkeit die 3 
Uhrzeit-Variaben aus den einzelnen Funktionen heraus zu ändern, ohne das 
ich die statischen Variablen benutzen muß ? Wenn ja, wie kann ich das am 
besten anstellen ?

Danke schon mal im voraus

Hans

von Rolf Magnus (Gast)


Lesenswert?

> Da es sich ja um eine Uhr handelt habe ich 3 Variablen stunden, minuten
> und sekunden. Diese habe ich dann als static gesetzt (global geht ja
> nur in einem .c File ?),

Was genau meinst du damit? Global heißt, daß es global, also überall 
verfügbar ist. Das gilt aber nicht, wenn du sie static machst. Nach 
deiner Beschreibung scheinst du es genau umgekehrt machen zu wollen.

> da ich mehrere "ausgelagerte" Funktionen in .c Files habe die die
> Uhrzeit-Variablen verändern bzw. benutzen (Uhrzeitstellen, eine
> Interruptroutine und die Ausgabefunktion ). Da ich die Variablen in
> Headerfiles drin hab, meckert das AVR-Studio nun andauernd über
> deklarierte aber nicht benutzte Variablen in main.

Statt das ellenlang zu erklären, hättest du auch ein paar Zeilen Code 
hinschreiben können, die es verständlicher erklären. Wenn du eine 
Variable im Header deklarierst, meckert der Compiler nicht.

> Jetzt meine Frage : Gibt es noch eine andere möglichkeit die 3
> Uhrzeit-Variaben aus den einzelnen Funktionen heraus zu ändern, ohne
> das ich die statischen Variablen benutzen muß ?

Wie kommst du überhaupt darauf, daß sie statisch sein müßten?

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Hallo Hans,

der C-Compiler includiert den Header in eine temporäre Datei. Diese wird 
dann erst übersetzt.

Wenn Du also schreibst

clock.h:
1
int iHour, iMinute, iSecond;
2
3
void setClock();
4
void getClock();

und in main:
1
#include "clock.h"
2
3
int main()
4
{
5
...
6
    setClock();
7
    getClock();
8
}

dann versteht der Compiler in tempMain.c:
1
int iHour, iMinute, iSecond;
2
3
int main()
4
{
5
...
6
    setClock();
7
    getClock();
8
}

und das in jeder Datei die den Header anzieht.

Du mußt schreiben:

clock.h:
1
extern int iHour, iMinute, iSecond;
2
3
void setClock();
4
void getClock();

und in clock.c:
1
static int iHour, iMinute, iSecond;
2
3
void setClock()
4
{
5
}
6
7
void getClock()
8
{
9
}

und in main.c die Variante von ganz oben (das was Du eigentlich dem 
Compiler sagen wolltest).

Gruß

Olaf

von Karl H. (kbuchegg)


Lesenswert?

Olaf Dreyer wrote:

Du hast so schön angefangen das zu erklären

> und in clock.c:
> static int iHour, iMinute, iSecond;

Fast. Ohne das static.

static an dieser Stelle bedeutet, dass die Variablen nur in
diesem File 'clock.c' bekannt sind. Daher kannst du dich dann
von anderen *.c nicht auf diese Variablen beziehen, weil der
Compiler dafür sorgt, dass diese Namen 'iHour, iMinute, iSecond'
ausserhalb von clock.c ganz einfach nicht existieren.

von Hans Melten (Gast)


Lesenswert?

Super, danke für die Antworten. Eine Frage habe ich noch, es ist leider 
einiges doch manchmal sehr unverständlich ( Obwohl ich schon 2 
verschiedene Bücher zu C gelesen habe)

>static an dieser Stelle bedeutet, dass die Variablen nur in
>diesem File 'clock.c' bekannt sind. Daher kannst du dich dann
>von anderen *.c nicht auf diese Variablen beziehen

Wenn ich dann jetzt in einem andern .c File die Variablen dann verwende, 
muss die in dem anderen .c File dann auch noch mal deklarieren oder 
reicht einmal ?

von Hans Melten (Gast)


Lesenswert?

Sorry, hat sich erledigt ;-)

Danke für die Hilfe, habe es endlich verstanden ... !

von Karl H. (kbuchegg)


Lesenswert?

Hans Melten wrote:

> Wenn ich dann jetzt in einem andern .c File die Variablen dann verwende,
> muss die in dem anderen .c File dann auch noch mal deklarieren oder
> reicht einmal ?

Deklarieren musst du sie jedesmal, wenn du sie verwendest.
Aber es darf nur eine Definition geben


a.c
****
1
extern int xyz;     // <-  das ist durch das extern eine Deklaration
2
                    // es besagt, dass es irgendwo eine Variable
3
                    // namens xyz gibt. Wo genau interessiert hier
4
                    // nicht. Der Compiler will nur wissen, dass
5
                    // es sie gibtund dass sie ein int ist
6
7
void foo()
8
{
9
  xyz = 5;          // ansonsten könnte man die Variable hier ja
10
                    // nicht verwenden
11
}

b.c
****
1
            // Eine Variable die irgendwo existiert, ist aber zuwenig.
2
            // Irgendwann muss ins kalte Wasser gesprungen werden,
3
            // und die Variable xyz muss tatsächlich irgendwo
4
            // definiert werden.
5
            // Warum nicht hier?
6
7
int xyz;    // hier wird die Variable xyz tatsächlich erzeugt.
8
            // Das ist eine Definition. Egal wieviele andere
9
            // *.c Files mittels extern auf eine Variable
10
            // xyz verweisen, hier ist diese Variable tatsächlich

von Hans Melten (Gast)


Lesenswert?

Ja, danke.
Habe es jetzt raus.
War eine schwierige Geburt, aber dank Deiner Hilfe habe ich es doch noch 
hinbekommen.
Das Programm läuft jetzt einwandfrei !

von Curtis (Gast)


Lesenswert?

Hallo,

man sollte sich klar machen, dass es in C keine globalen Variablen 
gibt. Die haben immer nur file scope, das heißt, sie sind nur dort 
bekannt, wo sie in der Datei stehen. Grob gesagt.

Curtis.

von Karl H. (kbuchegg)


Lesenswert?

Curtis wrote:
> Hallo,
>
> man sollte sich klar machen, dass es in C keine globalen Variablen
> gibt. Die haben immer nur file scope, das heißt, sie sind nur dort
> bekannt, wo sie in der Datei stehen. Grob gesagt.
>

Na ja. So würde ich das eher nicht ausdrücken.

Wenn schon, dann läuft es in heutigem C auf die Regelung
hinaus: Verwendet werden kann nur, was auch bekannt ist.
Und wenn es nur eine Deklaration ist, die etwas bekannt macht.

Das mit 'immer file scope' stimmt so schon mal gar nicht.
Es sei dann du verstehst unter scope etwas anderes als der
C-Standard.
Aber in C hat alles erst mal globalen Scope, es sei denn
es ist mittels static auf einen File Scope begrenzt. Globaler
Scope bedeutet, dass jede andere Compilation Unit nach Gutdünken
Funktionen und Variablen durch eine Deklaration referenzieren kann
die in einer anderen Compilation Unit definiert sind. Erst durch
static lässt sich diese externe Referenzierung verhindern. Man
könnte also durchaus sagen: Erst mal ist alles global. Um eine globale
Funktion und/oder Variable zu benutzen, genügt eine Deklaration
und man hat den Fuss in der Türe.

von Rolf Magnus (Gast)


Lesenswert?

> Wenn schon, dann läuft es in heutigem C auf die Regelung
> hinaus: Verwendet werden kann nur, was auch bekannt ist.

Das gilt aber auch nur für Variablen. Funktionen läßt es dich auch 
benutzen, wenn sie eigentlich unbekannt sind.

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus wrote:
>> Wenn schon, dann läuft es in heutigem C auf die Regelung
>> hinaus: Verwendet werden kann nur, was auch bekannt ist.
>
> Das gilt aber auch nur für Variablen. Funktionen läßt es dich auch
> benutzen, wenn sie eigentlich unbekannt sind.

Ja, leider :-)
Gibt es eigentlich Bestrebungen seitens des Standard-Gremiums,
hier eine Änderung zu machen?

Glauben tu ichs nicht, aber die Hoffnung stirbt zuletzt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger wrote:

> Gibt es eigentlich Bestrebungen seitens des Standard-Gremiums,
> hier eine Änderung zu machen?

Die Benutzung einer nicht deklarierten Funktion (impliziter
Ergebnistyp "int" und nicht spezifizierte Parameterliste) ist
ein hysterisches Fietscher und meiner Meinung nach ohnehin nicht
vom Standard abgedeckt.

Die Benutzung von Funktionen mit "K&R"-Deklaration (nicht-
prototypische Deklaration) ist vom C99-Standard als "obsolescent"
bezeichnet und damit potenzieller Kandidat, mal aus dem Standard
rauszufliegen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:

> Die Benutzung einer nicht deklarierten Funktion (impliziter
> Ergebnistyp "int" und nicht spezifizierte Parameterliste) ist
> ein hysterisches Fietscher und meiner Meinung nach ohnehin nicht
> vom Standard abgedeckt.

Gefunden, im Vorwort von ISO/IEC 9899:1999:

5 This second edition cancels and replaces the first edition, ISO/IEC
  9899:1990, as amended and corrected by ISO/IEC 9899/COR1:1994,
  ISO/IEC 9899/AMD1:1995, and ISO/IEC 9899/COR2:1996. Major changes
  from the previous edition include:

  [...]
  -- remove implicit function declaration

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich mach hier mal die Ingrid...

Jörg Wunsch wrote:

>   -- remove implicit function declaration

Folgerichtig warnt GCC bei -std=gnu99 und -std=c99 auch ohne jegliche
-W-Option darüber.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hi,

ich würde der einfachheit wegen ein struct vorschlagen.
1
struct timestruct
2
{
3
  int hour;
4
  int minute;
5
  int second;
6
};
7
8
timestruct time;
9
10
11
time.hour = 23;
12
time.minute = 59;
13
time.second = 59;

Der grosse Vorteil ist die sehr einfache Erweiterbarkeit, und die 
Übersichtlichkeit bleibt immer erhalten. Einfach
1
int day, int month, int milliseconds
 etc. in das struct und fertig.

Aisserdem macht dir z.B. der DevC als Editor entsprechende Vorschläge.



Hoffe mich nun nicht vertippt zu haben :-)


VG,
/r.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

1
struct timestruct
2
{
3
  int hour;
4
  int minute;
5
  int second;
6
};
7
8
timestruct time;

Das geht in C so nicht.  Eine struct bildet in C keinen eigenen
Namen ohne das Schlüsselwort "struct" (anders als in C++).

Einen wirklichen Mehrwert außer mehr Schreibarbeit sehe ich allerdings
darin nicht.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

ok, dann kommt noch nen typedef mit dazu :-)
Arbeite meist mit pointern, structs brauche ich selten, daher muss ich 
bei der syntax oft eben nachsehen ...

Daten, die einen gemeinsamen Nenner haben, sollte man aber immer 
zusammenfassen, allein der Lesbarkeit halber.

von Hans Melten (Gast)


Lesenswert?

Danke nochmals für die Zahlreichen Tips.

Einmal brauche ich aber noch eure Hilfe.
Und zwar geht um das OCR1A :
Ich habe eine config.h eingerichtet, wo ich wichtige Werte als #define 
gesetzt habe, unter anderem für den OCR1A mit #define UEBERLAUF 39999.
Wenn ich aber jetzt in meiner Timerroutine OCR1A = UEBERLAUF; eintrage, 
meckert WinAVR, das UEBERLAUF nicht deklariert ist.
Defines gelten doch überall im Programm ?? Andere defines Funktionieren 
Problemlos, wieso OCR1A nicht ? Liegt es daran das es ein 16Bit Reister 
ist ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hans Melten wrote:

> Wenn ich aber jetzt in meiner Timerroutine OCR1A = UEBERLAUF; eintrage,
> meckert WinAVR, das UEBERLAUF nicht deklariert ist.

Hast du denn auch ein
1
#include "config.h"

in deiner Applikation drin?

> Defines gelten doch überall im Programm ?

Nicht überall, sondern ab dem Moment, da der Compiler das #define
,,gesehen'' hat.

von Hans Melten (Gast)


Lesenswert?

Ja, ich hab das config.h direkt am Anfang von main.c vor allen anderen 
Header-Dateien.
Andere defines in verschiedenen Modulen funktionieren auch, nur eben 
OCR1A nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tippfehler?

An OCR1A liegt es bestimmt nicht (mal davon ausgehend, dass dein
Controller dieses Register auch tatsächlich hat ;-).

von Hans Melten (Gast)


Angehängte Dateien:

Lesenswert?

Habe den mega8, der hat doch das Register.
Ich hab jetzt mal ein mini-programm geschrieben mit dem define und der 
extra datei und auch da meckert er das nichts definiert ist.
Kannst Du dir das bitte mal anschauen ?

Vielleicht habe ich ja Mist gebaut, aber dann bitte nicht hauen ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich sehe nicht, wo die Datei timerinit.c ein #include "config.h"
machen würde.  Woher bitte soll der Compiler beim Compilieren
von timerinit.c dann UEBERLAUF kennen?

Wenn du das korrigierst geht es bis auf:
1
avr-gcc -mmcu=atmega8 -Wl,-Map=probier_hier.map main.o timerinit.o     -o probier_hier.elf
2
main.o: In function `main':
3
/tmp/x/probier_hier/default/../main.c:8: undefined reference to `Timer_init'

Timer_init() ist was anderes als Timer1_init(). ;-)

von Hans Melten (Gast)


Lesenswert?

Ohje, das war wohl noch zu früh...
Mal abgesehen vom falschen Funktionsaufruf.

Ich hatte verstanden wenn ich die config.h einmal in main.c aufrufe 
reicht das.
Also muss die config für jede .c Datei aufgerufen werden, wo das define 
verwendet wird ?

In meinen C-Büchern steht leider nix über Programme mit mehreren Dateien 
und wie man sowas alles einbindet :-/

von Johannes M. (johnny-m)


Lesenswert?

Hans Melten wrote:
> Also muss die config für jede .c Datei aufgerufen werden, wo das define
> verwendet wird ?
Tja, woher sonst soll der Compiler von dem Makro wissen? Du musst immer 
daran denken, dass der Compiler immer nur eine einzige Source-Datei 
sieht. Die anderen Dateien, die zum Projekt gehören, sind ihm in dem 
Moment völlig egal. Der Compiler bearbeitet jede einzelne Source-Datei 
so, als wäre sie die einzige auf der Welt. Erst der Linker macht aus den 
einzelnen Objekten, die der Compiler ausspuckt, ein zusammenhängendes 
Programm. Bis zu dem Zeitpunkt haben die einzelnen Dateien nichts 
miteinander zu tun. Dementsprechend muss alles, was der Compiler wissen 
muss, auch in der betreffenden Sourcedatei drinstecken bzw. vom 
Präprozessor über #include in das, was der Compiler letztendlich 
vorgesetzt bekommt, eingebaut werden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hans Melten wrote:

> Ich hatte verstanden wenn ich die config.h einmal in main.c aufrufe
> reicht das.

Scheint so, dass es mal Zeit wäre für einen Wiki-Artikel, der die
Funktion des Präprozessors erläutert...  (Solche Fragen wie deine
tauchen einfach immer wieder auf.)

Dein grundlegender Denkfehler ist, dass du config.h aufrufen
würdest.  “include” heißt ja weiter nichts als ,,zieh den Text
der Datei hier rein''.  Das Ergebnis der gesamten Kette einer
Quelldatei und all ihrer include-Dateien ist das, was der
C-Standard dann etwas hochtrabend klingend eine “compilation unit”
nennt: der C-Quelltext, der vom Compiler auf ein Mal compiliert
wird.

Der Präprozessor ist ein reiner Textverarbeiter.  Er nimmt sich
alle Zeilen, die mit # beginnen und such darin nach Anweisungen
für sich.  Bei einem #include wird die entsprechende Datei eingefügt.
Der Rest des durchlaufenden Textes wird noch auf C-Bezeichner hin
überprüft um zu schauen, ob der entsprechende Bezeichner zuvor mittels
#define als Makro definiert worden war.  Wenn dem so ist, wird er im
laufenden Text durch die rechte Seite des Makros substituiert.

von Hans Melten (Gast)


Lesenswert?

>Scheint so, dass es mal Zeit wäre für einen Wiki-Artikel, der die
>Funktion des Präprozessors erläutert

Ja, ich hätte nichts dagegen gehabt. Die Anfänge sind halt manchmal 
schwer ...

Das das #include nur den Text ersetzt hatte ich verstanden, nur halt 
nicht, das es nicht reicht einmal eine config.h aufzurufen.
Sondern das in jeder .c Datei auch wieder die config aufgerufen werden 
muß.

Von oben her hatte ich es so verstanden, das alle C-Dateien einfach 
hintereinander gereiht werden und das dann das, was die vorherige c. 
Datei schon kennt, die nächste c. Datei automatisch auch kennt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hans Melten wrote:

> Von oben her hatte ich es so verstanden, das alle C-Dateien einfach
> hintereinander gereiht werden

Nein, jede wird für sich separat übersetzt.  Die sich daraus
ergebenden (verschieblichen) Objektdateien werden dann vom Linker
zusammengefügt, wobei alle bis dahin offenen externen Referenzen
aufgelöst werden.

Es gibt allerdings in der Tat Compiler, die wie von dir beschrieben
vorgehen.  Die müssten dann aber, wenn sie konform zum C-Standard
sein wollen, zwischen den einzelnen C-Dateien die Inhalte aller
bereits gesehenen nicht-globalen Objekte und Funktionen und auch
aller Includes wieder ,,vergessen''.

von Jens-Erwin (Gast)


Lesenswert?

Ich arbeite lange schon mit folgender Struktur:

Alle c-Dateien haben nur EINEN include, nämlich #include "Main.h"

auch die Main.c hat nur diesen EINEN include-Hinweis

die Main.h hat dann alle anderen "includes", auch die eigenen anderen 
h-Dateien

z.B.

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdlib.h>


#include "Midi.h"
#include "Wasserspiele.h"
#include "Klangspiele.h"

damit wird alles übersichtlich, in den h-Dateien stehen Tabellen, 
Definitionen, Funktionsverweise, Variablen usw.

Das funktioniert gut und ist auch logisch -- oder?

von Falk B. (falk)


Lesenswert?

@ Jens-Erwin (Gast)

>Alle c-Dateien haben nur EINEN include, nämlich #include "Main.h"

Eher schlecht.

>Das funktioniert gut und ist auch logisch -- oder?

Nöö. Wenn du in einem grossen Projekt nur EINE Datei änderst, muss ALLES 
neu übersetzt werden. Nicht gut.

Ergo. Jede C-Datei hat nur die includes, die WIRKLICH gebraucht werden.

MfG
Falk

von Jens-Erwin (Gast)


Lesenswert?

Das sind schon auch große Projekte aber eben nur für uC. Für einen uC 
wie den AVR ist das übersetzen aller Dateien doch gar kein Problem.

Außerdem ging es ja um eine gewisse Übersichtlichkeit für Anfänger und 
in einen AVR z.B. passt gar nicht so viel rein. Da kann schon alles 
übersetzt werden. Jedenfalls wird so nie gemeckert, dass der Compiler 
irgendwas nicht finden würde ...

von Simon K. (simon) Benutzerseite


Lesenswert?

Jens-Erwin wrote:
> Das sind schon auch große Projekte aber eben nur für uC. Für einen uC
> wie den AVR ist das übersetzen aller Dateien doch gar kein Problem.

Der AVR übersetzt überhaupt nichts!

> Außerdem ging es ja um eine gewisse Übersichtlichkeit für Anfänger und
> in einen AVR z.B. passt gar nicht so viel rein. Da kann schon alles
> übersetzt werden. Jedenfalls wird so nie gemeckert, dass der Compiler
> irgendwas nicht finden würde ...

Und mit der Codegröße hat das auch nichts zu tun.

Aber das Kompilieren dauert, gerade bei großen Projekte, wesentlich 
länger wenn 90% der Zeit unnütze Headerfiles abgearbeitet werden müssen.

von Rolf Magnus (Gast)


Lesenswert?

>> Das sind schon auch große Projekte aber eben nur für uC. Für einen uC
>> wie den AVR ist das übersetzen aller Dateien doch gar kein Problem.
>
> Der AVR übersetzt überhaupt nichts!

Ich glaube, es war eher so gemeint: "Das Übersetzen für den AVR ist kein 
Problem". Gemeint war wohl, daß AVR-Projekte klein genug sind, um auch 
mit vielen Headern schnell genug übersetzt werden zu können.
Das würde mit meiner Arbeitsweise aber nur bedingt gelten. Ich lasse 
meinen Code sehr oft durch den Compiler laufen (auch öfter, als ich es 
flashen würde), nur um zu sehen, ob nicht ein Flüchtigkeitsfehler drin 
ist. Wenn da praktisch nach jeder kleinen Änderung immer erst das 
gesamte Projekt übersetzt werden müßte, würde mir das zu lange dauern. 
Dann könnte ich mir die tolle Aufteilung auch sparen und gleich alles in 
ein riesiges C-File schreiben.

> Und mit der Codegröße hat das auch nichts zu tun.

Doch schon. Wenn in den Prozessor nicht viel reinpasst, bleibt 
tendenziell der Quellcode kleiner und kann vom Compiler schneller 
übersetzt werden, so die Theorie. ;-)

von Jens-Erwin (Gast)


Lesenswert?

Genau so wollte ich es verstanden haben .... Danke

Es ist schon übersichtlicher quasi "ein" C-File in mehrere "kleinere" 
Files aufzuteilen, um damit die einzelnen Themen übersichtlicher zu 
bearbeiten und vielleicht auch in andere (ähnliche) Projekte zu 
übertragen.

Mir hat's jedenfalls geholfen und hilft noch ...

von Jens-Erwin (Gast)


Lesenswert?

Jedes einzelne File ist compilierbar -- Alt+F7

auch wenn alle c-Dateien auf eine h-Datei, die wiederum andere h-Dateien 
includieren kann, zugreifen ...

--- das spart wirklich Zeit -- toll


Dann ist diese Methode GENIAL

-- Idee hat mir übrigens vor Jahren mal jemand aus dem Forum empfohlen 
---

von Hubba Bubba (Gast)


Lesenswert?

Toll

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.