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?
Chandler B. schrieb:> wie benutze ich solche sachen jetzt im Code? Einfach als uint16_t?> Also das würde gehen, aber ist das so der richtige weg?
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.
Chandler B. schrieb:> Einfach als uint16_t?
Der default Datentype für enum ist in, nicht uintxxxx.
Das dürfte auch in deinem C Buch so stehen.
Ist doch C, oder?
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.
Arduino F. schrieb:> Der default Datentype für enum ist in, nicht uintxxxx.> Das dürfte auch in deinem C Buch so stehen.
Ja, das denke ich mir auch, da ich ja eigentlich gar nicht weiß, wie
groß der Datentyp wirklich ist.
Aber als irgendwas muss ich das ja benutzen können.
Arduino F. schrieb:> Ist doch C, oder?
Ja, ist C
Cyblord -. schrieb:> Wüsste ich jetzt auch nicht wie> man das benutzt.
Gar nicht!
Es ist nicht mehr als eine Liste von Konstanten.
Eine einfachere Schreibweise von:
1
constintSBC_MODE_NORMAL=0x00;
2
constintSBC_MODE_SLEEP=0x00+1;
Mit automatisch hochzählender Initialisierung.
Natürlich könnte man auch #define verwenden
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.
Cyblord -. schrieb:> Ist aber hässlich und unnötig.
Der springende, nützliche, Punkt ist das automatische Hochzählen.
Manuelles hochzählen ist mühsam und Fehlerträchtig.
Arduino F. schrieb:> Cyblord -. schrieb:>> Ist aber hässlich und unnötig.>> Der springende, nützliche, Punkt ist das automatische Hochzählen.> Manuelles hochzählen ist mühsam und Fehlerträchtig.
Aber was hindert einen daran dafür ein gültiges enum mit Namen zu
erzeugen?
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.
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.
Johann L. schrieb:> Arduino F. schrieb:>> Der springende, nützliche, Punkt ist>> Die eigentliche Frage ist: Was soll das typedef?
Oh ja.
> Ein Typ wird ja nicht definiert, funktioniert also nur wegen irgendeiner> komischen C/C++ Syntax-Regel.
Ganz ehrlich: Das Konstrukt sieht mir typisch "indisch" aus. Wenn ich
wetten müsste woher der Code für diesen Generator stammt...
enum { A, B, C }; ergibt Sinn.
typedef enum { A, B, C }; ist syntaktisch zulässig und hat die gleiche
Bedeutung, ist aber eher verwirrend als sinnvoll.
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.
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;
(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.
;-)
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:
Arduino F. schrieb:> (prx) A. K. schrieb:>> typedef gab es anfangs auch nicht.>> Und in C++ ist es noch vorhanden, aber quasi nutzlos.
Warum sollte es nutzlos sein? Es macht noch das gleiche wie immer.
Rolf M. schrieb:> Warum sollte es nutzlos sein?
Weil man es nicht mehr braucht!
Rolf M. schrieb:> Es macht noch das gleiche wie immer.
Gut, wenn man historischen C++ oder C Code integriert, dass es noch das
gleiche tut.
Aber sonst...
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?
Arduino F. schrieb:> Richtig!
OK, danke 👍
Arduino F. schrieb:> Vorlieben halt ....
Je nach dem vielleicht auch der Zwang durch den letzten möglichen
Compiler. Wobei das schon seit Cpp11 drin ist wenn ich richtig geschaut
habe.
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.
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 😁
Arduino F. schrieb:> N. M. schrieb:>> Wie würdest du sowas ohne typedef machen?>> Using?>> Richtig!> using LedRed = Combie::Pin::OutputPin<red>;> using FuncPtr = void(*)();> FuncPtr test = nullptr;>> 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.
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<typenameT>usingintmap=std::map<int,T>;// OK
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.
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.
(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
usingS=structS
2
{
3
S*next;
4
};
Aber der using-Teil ist an der Stelle ziemlich sinnbefreit.
Rolf M. schrieb:> Das ist doch für C++ überhaupt nicht relevant
Stimmt, nur ist C++ in diesem Thread überhaupt nicht relevant. :)
Chandler B. schrieb:> Ja, ist C
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.
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.
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.
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:
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
>structA{};
2
>structB{};
3
>usingC=A;
4
>
5
>Aa;
6
>Bb=a;// Fehler, da anderer Typ
7
>Cc=a;// Ok, da der selbe Typ
8
>
Verhält sich aber so wie
1
structA{};
2
structB{};
3
typedefAC;
4
Aa;
5
Bb=a;// Fehler, da anderer Typ
6
Cc=a;// Ok, da der selbe Typ
Dein Beispiel sollte aber twischen "Typ-Alias" und "neuer Typ"
unterscheiden, oder nicht?
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.
Johann L. schrieb:> Verhält sich aber so wie
Natürlich!
In dem Fall ist es völlig egal, ob typedef oder using.
Es ist eher eine Frage der Gewöhnung.
Wer aus der C Ecke kommt oder früh mit C++ angefangen hat, wird wohl zu
typedef tendieren.
Johann L. schrieb:> Rolf M. schrieb:> 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.
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
Johann L. schrieb:> Und wo ist jetzt der Unterschied zwischen c und d?
Nur der Type Alias Bezeichner.
Sonst gibt es keinen!
Aber das sagte ich doch auch schon.
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.
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
typedefAC;
3
usingD=A;
1
// Variante 2
2
typedefAC;
3
typedefAD;
1
// Variante 3
2
usingC=A;
3
usingD=A;
1
// Variante 4
2
typedefAD;
3
usingC=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).
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
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
Arduino F. schrieb:> Die Funktion "sieht" nur den grundlegenden Datentype, kümmert sich um> irgendwelche Aliase
Da fehlt ein "nicht".
Die Funktion "sieht" nur den grundlegenden Datentype, kümmert sich nicht
um irgendwelche Aliase
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.
Hans-Georg L. schrieb:> P2360R0 inconsistency between typedef declarations and alias> declarations will have been removed.
Das ist allerdings eine wichtige Ergänzung ;)
Oliver