Typedef enum ohne Namen

OP #7961876
Lesenswert?

Hallo, wenn ich mir für den TLE9471 dateien mit dem Wizard generieren lasse, bekomme ich in TLE94x1_DEFINES.h eine menge typedef enums, aber ohne Namen. z.B.

1
typedef enum
2
{
3
    SBC_MODE_NORMAL                         = 0x00U,
4
    SBC_MODE_SLEEP,
5
    SBC_MODE_STOP,
6
    SBC_MODE_RESET
7
};

Dies gibt mir beim compilieren auch die Warnung: "useless storage class specifier in empty declaration"

wie benutze ich solche sachen jetzt im Code? Einfach als uint16_t? Also das würde gehen, aber ist das so der richtige weg?

: Bearbeitet durch User
OP #7961890
Lesenswert?

Oliver S. schrieb:

Welche Programmiersprache der beiden wahrscheinlichsten Möglixhkeiten nutzt du denn?

Oliver

C

Cyblord -. schrieb:

Ein typedef und enum ohne jeden Namen? Wüsste ich jetzt auch nicht wie man das benutzt. Wird sicher eine kranke Makro-Vergewaltigung geben bei der man das nutzen kann. Leute die normal im Kopf sind lassen die Finger von sowas.

Nun ja, das ist von Infineon automatisch generierter Code, den ich in mein Projekt einbinden kann, um mit dem TLE9471 zu arbeiten.

#7961894
Lesenswert?

Chandler B. schrieb:

Ja, das denke ich mir auch, da ich ja eigentlich gar nicht weiß, wie groß der Datentyp wirklich ist.

Doch weil ein enum immer ein int ist. Anders würde es bei einem struct aussehen.

Aber als irgendwas muss ich das ja benutzen können.

Denke nicht. Wüsste nicht wie. Also nicht sinnvoll. Natürlich kann man das einfach als Konstanten nutzen. Ist aber hässlich und unnötig. Und in C IMO nicht erlaubt. In C++ vielleicht? Weiß ich nicht.

: Bearbeitet durch User
(Firma: Gast) #7961902
Lesenswert?

Cyblord -. schrieb:

Aber was hindert einen daran dafür ein gültiges enum mit Namen zu erzeugen?

Wenn/Warum es der Codegenerator nicht tut? KA, ist nicht meine Baustelle.

Vielleicht weniger Bezeichner im betreffenden Namensraum. Also auch weniger Kollisionen mit fremden "Code Modulen"

Anonyme enum sind übrigens in C++ kein Problem, nur das typedef wird angemeckert, weil unnötig.

(Firma: Gast) #7961913
Lesenswert?

In C++ würde man das eher so, oder so ähnlich, schreiben:

1
enum class SBC_MODE : uint8_t
2
{
3
    NORMAL                         = 0x00U,
4
    SLEEP,
5
    STOP,
6
    RESET
7
};
8

9
void setup() 
10
{
11
  Serial.begin(9600);
12

13
  Serial.println(uint8_t(SBC_MODE::RESET));
14
}
15

16
void loop() 
17
{
18

19
}

Also mit Bezeichner, und strenger Typisierung. Wobei die Strenge den Zugriff auf das Value etwas erschwert.

#7961962
Lesenswert?

Johann L. schrieb:

Ein Typ wird ja nicht definiert, funktioniert also nur wegen irgendeiner komischen C/C++ Syntax-Regel.

Syntaktisch ist das vergleichbar zu extern int; oder auch nur int; und zulässig, da eine Liste von Namen wie int a, b, c; leer sein kann. Andernfalls wäre enum { A, B, C }; syntaktisch auch nicht zulässig.

Die Syntax von C ist nicht wirklich tief durchdacht.

: Bearbeitet durch User
#7962017
Lesenswert?

Man kann diesen höheren Blödsinn noch fortsetzen. Der Typ ist ja optional, fehlt er, gibt es int. Weshalb sich extern int a; zu extern a; abkürzen lässt. Mit leerer Liste der Namen geht also auch extern; Da typedef syntaktisch eine storage class wie extern ist, geht auch typedef;

: Bearbeitet durch User
Moderator #7962019
Lesenswert?

(prx) A. K. schrieb:

Man kann diesen höheren Blödsinn noch fortsetzen. Der Typ ist ja optional, fehlt er, gibt es int. Weshalb sich extern int a; zu extern a; abkürzen lässt. Mit leerer Liste der Namen geht also auch extern; Da typedef syntaktisch eine storage class wie extern ist, geht auch typedef;

Auch das extern bzw. typedef kann man weglassen. Übrig bleibt ein extrem ausdruckstarkes

1
;

Aber auch dieses kann weggelassen werden:

Ups =8-o

Leider versagt dann die C-Code-Formatierung der Forensoftware.

;-)

: Bearbeitet durch Moderator
#7962368
Lesenswert?

Johann L. schrieb:

Arduino F. schrieb:

Der springende, nützliche, Punkt ist

Die eigentliche Frage ist: Was soll das typedef?

Ein Typ wird ja nicht definiert, funktioniert also nur wegen irgendeiner komischen C/C++ Syntax-Regel.

Ja, der einzige Zweck von typedef ist, einem Typ einen neuen Namen zu geben. Wenn man diesen Namen dann weglässt, ist es vollkommen sinnlos.

(prx) A. K. schrieb:

Man kann diesen höheren Blödsinn noch fortsetzen. Der Typ ist ja optional, fehlt er, gibt es int.

Das kommt aus der Historie von C, bei der Typnamen fast überall optional waren. void gab es anfangs nicht, und ohne Angabe wurde immer implizit int verwendet, z.B. auch beim Return-Typ von Funktionen. Und wo es heute den meisten gar nicht bewsusst ist: short und long sind eigentlich auch keine Typen, sondern nur Typ-Modifiers. Die Typen heißen eigentlich short int und long int.

Lustig ist auch, dass man das ganze Zeug auch wild durcheinander mischen kann. So geht z.B. auch:

1
short unsigned typedef const my_type;
: Bearbeitet durch User
#7962536
Lesenswert?

Arduino F. schrieb:

Weil man es nicht mehr braucht!

Gerade wenn man mit Templates arbeitet finde ich es gut wenn man den Typ den man verwenden möchte einmal definieren kann und dann einen kompakten Ausdruck hat. Ansonsten dreht man da irgendwann durch wenn man das immer mit schleppen muss.

Wie würdest du sowas ohne typedef machen? Using?

: Bearbeitet durch User
(Firma: Gast) #7962592
Lesenswert?

N. M. schrieb:

vielleicht auch der Zwang

Kein Zwang! Denn typedef tuts ja weiterhin.

N. M. schrieb:

durch den letzten möglichen Compiler

Da steckt eher der Wunsch hinter, mit der neuesten Version zu arbeiten und die neuesten Features auszuprobieren. Einige neue Features kann man auch in meiner kleinen µC Welt einsetzen. Using gehört (für mich) eindeutig dazu.

Nutze übrigens z.Zt. AVR-Gcc 15.2 C++23 mit einer eingeschränkten libstdc++ in der Arduino IDE. Der große Rest der AVR Arduino Welt dümpelt meist noch bei Gcc 7.3 und C++11

N. M. schrieb:

danke

Gerne auch.

N. M. schrieb:

das schon seit Cpp11 drin ist

Ja, seit min 14 Jahren nutzbar.

: Bearbeitet durch User
#7962632
Lesenswert?

Arduino F. schrieb:

Kein Zwang! Denn typedef tuts ja weiterhin.

Das war anders gemeint. Zwang typedef nutzen zu müssen weil der Compiler so alt ist das using schlicht nicht geht. In einem Projekt habe ich den Fall dass erst vor 1 Jahr ein Update auf Cpp11 möglich war. Wenn man dann Code über mehrere Projekte wiederverwenden möchte ist es schwierig/unmöglich zu neuem Syntax zu wechseln.

Arduino F. schrieb:

Nutze übrigens z.Zt. AVR-Gcc 15.2 C++23 mit einer eingeschränkten libstdc++

Das ist schon Luxus 😁

Moderator #7962665
Lesenswert?

Rolf M. schrieb:

Mir liegt using eher als typedef. Mag für andere anders aussehen. Vorlieben halt ....

Ja, bei mir ist es gerade umgekehrt, wegen der inkonsistenten Syntax.

Die Deklaration von Typaliassen mit using ist allgemeiner, da sie auch getemplatet werden kann. Beispiel:

1
#include <map>
2

3
template <typename T> using intmap = std::map<int, T>;   // OK
4

5
template <typename T> typedef std::map<int, T> intmap;   // Fehler

Deswegen gibt es das typedef nur noch wegen der Abwärtskompatibilität.

#7962756
Lesenswert?

Yalu X. schrieb:

Die Deklaration von Typaliassen mit using ist allgemeiner, da sie auch getemplatet werden kann. Beispiel: #include <map> template <typename T> using intmap = std::map<int, T>; // OK template <typename T> typedef std::map<int, T> intmap; // Fehler

Wobei man dieses Feature ja eigentlich auch problemlos den typedefs hätte geben können.

#7962757
Lesenswert?

Yalu X. schrieb:

Die Deklaration von Typaliassen mit using ist

... endlich mit vernünftiger Syntax versehen worden.

Die Syntax von typedef wurde in C ziemlich beknackt definiert, denn bei typedef struct S { struct S *next; } S; muss man drinnen den Struct-Namen nutzen, weil der Typ-Name noch nicht existiert.

: Bearbeitet durch User
#7962776
Lesenswert?

(prx) A. K. schrieb:

Yalu X. schrieb:

Die Deklaration von Typaliassen mit using ist

... endlich mit vernünftiger Syntax versehen worden.

Die Syntax von typedef wurde in C ziemlich beknackt definiert, denn bei typedef struct S { struct S *next; } S; muss man drinnen den Struct-Namen nutzen, weil der Typ-Name noch nicht existiert.

Das ist doch für C++ überhaupt nicht relevant, und in C gibt's kein using. Gut, man könnte zwar wohl schreiben:

1
using S = struct S
2
{
3
    S *next;
4
};

Aber der using-Teil ist an der Stelle ziemlich sinnbefreit.

#7962791
Lesenswert?

Yalu X. schrieb:

Die Deklaration von Typaliassen mit using ist allgemeiner, da sie auch getemplatet werden kann. Beispiel:

1
> #include <map>
2
> 
3
> template <typename T> using intmap = std::map<int, T>;   // OK
4
> 
5
> template <typename T> typedef std::map<int, T> intmap;   // Fehler
6
>

Erzeugt 'using' eigentlich einen neuen Typ? Z.B. wenn man irgendein template gebastelt hat und die implementierten Spezialisierungen davon in der .cpp verstecken will. Wenn dem so wäre, dann machts schon einen Unterschied und böte einen Vorteil, auf typedef zu verzichten. using könnte dann das Leben mit dem Linker einfacher machen.

#7962809
Lesenswert?

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nein, using vergibt wie typedef nur einen neuen Namen. Wenn ich einen Typ A definiere und using B = A schreibe, dann sind A und B ein und derselbe Typ.

Z.B. wenn man irgendein template gebastelt hat und die implementierten Spezialisierungen davon in der .cpp verstecken will.

Klingt als wäre das eher was für explizite Template-Instanziierung.

(prx) A. K. schrieb:

Rolf M. schrieb:

Das ist doch für C++ überhaupt nicht relevant

Stimmt, nur ist C++ in diesem Thread überhaupt nicht relevant. :)

Dann ist aber using auch nicht relevant, da es das wie gesagt in C nicht gibt.

: Bearbeitet durch User
Persönliche Seite #7962815
Lesenswert?

Arduino F. schrieb:

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nöö... Es wird ein Type Alias erzeugt.

Wobei das wohl auf Sprachebene auf 100% das gleiche rauskommt und nicht unterschieden werden kann. Lediglich ein anderes Wording in der Spezifikation, mehr nicht. Wie ein Compiler das tatsächlich implementiert sieht man auf Sprachebene auch nicht.

#7962826
Lesenswert?

Johann L. schrieb:

Arduino F. schrieb:

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nöö... Es wird ein Type Alias erzeugt.

Wobei das wohl auf Sprachebene auf 100% das gleiche rauskommt und nicht unterschieden werden kann.

Na sicher kann das unterschieden werden:

1
struct A { };
2
struct B { };
3
using C = A;
4

5
A a;
6
B b = a; // Fehler, da anderer Typ
7
C c = a; // Ok, da der selbe Typ
Persönliche Seite #7962860
Lesenswert?

Rolf M. schrieb:

Johann L. schrieb:

Arduino F. schrieb:

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nöö... Es wird ein Type Alias erzeugt.

Wobei das wohl auf Sprachebene auf 100% das gleiche rauskommt und nicht unterschieden werden kann.

Na sicher kann das unterschieden werden:

1
> struct A { };
2
> struct B { };
3
> using C = A;
4
> 
5
> A a;
6
> B b = a; // Fehler, da anderer Typ
7
> C c = a; // Ok, da der selbe Typ
8
>

Verhält sich aber so wie

1
struct A { };
2
struct B { };
3
typedef A C;
4
A a;
5
B b = a; // Fehler, da anderer Typ
6
C c = a; // Ok, da der selbe Typ

Dein Beispiel sollte aber twischen "Typ-Alias" und "neuer Typ" unterscheiden, oder nicht?

#7962867
Lesenswert?

Johann L. schrieb:

Dein Beispiel sollte aber twischen "Typ-Alias" und "neuer Typ" unterscheiden, oder nicht?

Ja, ging es nicht darum?

Johann L. schrieb:

Arduino F. schrieb:

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nöö... Es wird ein Type Alias erzeugt.

Wobei das wohl auf Sprachebene auf 100% das gleiche rauskommt und nicht unterschieden werden kann.

Da steht ja nix von typedef, nur von Alias vs neuer Typ.

Zwischen einem Alias, das per using erzeugt wurde und einem per typedef sollte soweit ich weiß kein Unterschied bestehen.

Persönliche Seite #7962876
Lesenswert?

Johann L. schrieb:

Rolf M. schrieb im Beitrag #7962826: Dein Beispiel sollte aber twischen "Typ-Alias" und "neuer Typ" unterscheiden, oder nicht?

Nein. DU hast behauptet, ein Typ-Alias lasse sich von einem "neuen Typ" unterscheiden und hattest ein angebliches Beispiel dazu gegeben.

Ich hatte geschrieben:

Johann L. schrieb:

Arduino F. schrieb:

Falk S. schrieb:

Erzeugt 'using' eigentlich einen neuen Typ?

Nöö... Es wird ein Type Alias erzeugt.

Wobei das wohl auf Sprachebene auf 100% das gleiche rauskommt und nicht unterschieden werden kann. Lediglich ein anderes Wording in der Spezifikation, mehr nicht. Wie ein Compiler das tatsächlich implementiert sieht man auf Sprachebene auch nicht.

: Bearbeitet durch User
(Firma: Gast) #7962895
Lesenswert?

Ach...

Der Nachweis, dass nur ein Alias erzeugt wird, ist doch leicht zu führen

Testcode:

1
struct A { };
2
struct B { };
3

4
typedef A C;
5
using D = A;
6
A a;
7
B b;
8

9

10
C c = a; // Ok, da der selbe Typ
11
D d = a; // Ok, da der selbe Typ
12

13
template<typename T> void pretty(T&,T&) { Serial.println(__PRETTY_FUNCTION__);}
14
template<typename U,typename V> void pretty(U&,V&) { Serial.println(__PRETTY_FUNCTION__);}
15

16
void setup() 
17
{
18
  Serial.begin(9600);
19
  pretty(a,c);
20
  pretty(a,d);
21
  pretty(b,d);
22
}
23

24
void loop() 
25
{
26

27
}

Ausgabe:

1
void pretty(T&, T&) [with T = A]
2
void pretty(T&, T&) [with T = A]
3
void pretty(U&, V&) [with U = B; V = A]
Persönliche Seite #7962909
Lesenswert?

Arduino F. schrieb:

Ach...

Der Nachweis, dass nur ein Alias erzeugt wird, ist doch leicht zu führen typedef A C; using D = A; A a; B b;

C c = a; // Ok, da der selbe Typ D d = a; // Ok, da der selbe Typ

... pretty(a,c); pretty(a,d); ... Ausgabe: void pretty(T&, T&) [with T = A] void pretty(T&, T&) [with T = A] void pretty(U&, V&) [with U = B; V = A]

Und wo ist jetzt der Unterschied zwischen c und d?

Arduino F. schrieb:

Ach...

Der Nachweis, dass nur ein Alias erzeugt wird, ist doch leicht zu führen typedef A C; using D = A; A a; B b;

C c = a; // Ok, da der selbe Typ D d = a; // Ok, da der selbe Typ

... pretty(a,c); pretty(a,d); ... Ausgabe: void pretty(T&, T&) [with T = A] void pretty(T&, T&) [with T = A] void pretty(U&, V&) [with U = B; V = A]

Und wo ist jetzt der Unterschied zwischen c und d?

formerror_too_many_quoted_lines

#7962920
Lesenswert?

Ok, danke für die Antworten, typedef und using unterscheiden sich wohl also nicht wirklich. Ich hab mir aufbauend auf Eure Ideen mal kurz einen Test gebaut, dabei hat der Compiler über Mehrfachdefinition der Spezialisierung gemeckert - würde er ja vermutlich nicht tun, wenn es ein anderer Typ wäre.

1
#include <iostream>
2
#include <vector>
3

4
using ContainerFoo = std::vector<int>;
5
typedef std::vector<int> ContainerBar;
6

7
// decl
8
template<typename T>
9
void myFunction(const T& blub);
10

11
// def
12
template<>
13
void myFunction(const ContainerFoo& blub) {}
14

15
template<>
16
void myFunction(const ContainerBar& bla) {}
17

18
// usage
19
int main()
20
{
21
    ContainerFoo foo{1,2,3,4,5};
22
    ContainerBar bar{5,6,7,8,9};
23
    
24
    myFunction<>(foo);
25
    myFunction<>(bar);
26
}
Persönliche Seite #7962926
Lesenswert?

Arduino F. schrieb:

Johann L. schrieb:

Und wo ist jetzt der Unterschied zwischen c und d?

Nur der Type Alias Bezeichner. Sonst gibt es keinen!

Sorry, ich versteh's immer noch nicht. Für folgende 4 Varianten deines Beispiels bekomme ich exakt die gleiche Ausgabe:

1
// Variante 1 (Orginal)
2
typedef A C;
3
using D = A;
1
// Variante 2
2
typedef A C;
3
typedef A D;
1
// Variante 3
2
using C = A;
3
using D = A;
1
// Variante 4
2
typedef A D;
3
using C = A;

In allen Varianten ist die Ausgabe:

1
void pretty(T&, T&) [with T = A]
2
void pretty(T&, T&) [with T = A]
3
void pretty(U&, V&) [with U = B; V = A]

Oben wurde auch geschrieben, dass sich typedef und using genau gleich verhalten (mit der Ausnahme, dass using eine echte Obermenge von typedef ist).

(Firma: Gast) #7962933
Lesenswert?

Johann L. schrieb:

Für folgende 4 Varianten deines Beispiels bekomme ich exakt die gleiche Ausgabe:

Ja! Das ist auch richtig so. Der Alias dient nur dazu, es Menschenlesbarer zu machen. Der grundlegende Datentype bleibt dabei gleich.

Ob typedef oder using spielt dabei keinerlei Rolle. Die Funktion "sieht" nur den grundlegenden Datentype, kümmert sich um irgendwelche Aliase

: Bearbeitet durch User
#7963103
Lesenswert?

Oliver S. schrieb:

Zitat von cppreference.com:

„There is no difference between a type alias declaration and typedef declaration.“

type alias meint „using“.

Aber vielleicht schreibt ja noch mal jemand ein paar hundert Zeilen Code, um das zu bestätigen.

Oliver

Es gibt keine Unterschiede in der Syntax. Es gibt/gab aber kleine Unterschiede wo using/typedef erlaubt ist. Das wurde mit C++23 behoben. P2360R0 inconsistency between typedef declarations and alias declarations will have been removed.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren