Die Bedeutung der beiden Namen wird klarer, wenn man es in zwei Schritte
aufteilt. Mal ein einfacheres Beispiel:
1 | struct xy_struct {
|
2 | uint8_t x;
|
3 | uint8_t y;
|
4 | };
|
Das sagt dem Compiler, was ein "struct xy_struct" prinzipiell ist. Hier
also, dass es zwei Variablen x und y vom Typ uint8_t enthält. Es wird
noch keine Variable und damit Speicher reserviert, es ist eine reine
Information für den Compiler.
Das Anlegen der Variable passiert hier:
1 | struct xy_struct mein_xy1;
|
2 | struct xy_struct mein_xy2;
|
Hier werden zwei Variablen vom Typ "struct xy_struct" angelegt. Dafür
werden insgesamt vier Byte Speicher reserviert. Man kann auf ein
einzelnes Element dann z.B. per mein_xy1.x zugreifen.
Man kann diese beiden Schritte auch in einen zusammenziehen:
1 | struct xy_struct {
|
2 | uint8_t x;
|
3 | uint8_t y;
|
4 | } mein_xy1;
|
Hier wurde deklariert, was ein "struct xy_struct" ist und gleichzeitig
die Variable mein_xy1 mit diesem Typ angelegt.
Dadurch, dass die Struktur einen Namen hat, kann man später noch mehr
Variablen davon anlegen:
1 | struct xy_struct mein_xy2;
|
Oder auch eine Funktion definieren, die etwas mit dieser Struktur macht:
1 | void print_x(struct xy_struct xy) {
|
2 | putchar(xy.x);
|
3 | }
|
Das gleiche ist in Deinem Beispiel mit der Union der Fall. Dort wurde
für den Namen der Union (des Typs) und für den Variablennamen der
gleiche Bezeichner gewählt. Das ist wie gesagt ziemlich ungeschickt und
sollte man nicht machen.