Hi,
ich frage mich etwas: Geht es in C nicht oder was mache ich falsch?!
Um ehrlich zu sein, ich hätte sowas schon öfters gebraucht, ging zwar
auch anders, etwas unsauber, aber war ok. In diesem Fall (klar geht auch
anders), aber das wird gigantisch doof.
1
enum_states
2
{
3
stop,
4
go,
5
slow1,
6
slow2,
7
ks1,
8
ks2,
9
ks3
10
}signalstate;
11
12
uint8_tstate=signalstate.stop;
Sowas möchte ich, sprich state kann nur Werte von signalstate bekommen,
und die Werte im enum möchte ich nicht aufrufen indem ich schreibe
"stop" usw.. sondern nur wenn ich den Enumnamen davorschreibe damit ich
auch nur das stop habe und nicht ein stop aus einem anderen enum.
Gehts? Gehts nicht? Bitte um Hilfe!
P.S. Ich finde die Fehlermeldung dabei geil:
request for member 'stop' in something not a structure or union
In "something". ~
MOBA 2. schrieb:> Sowas möchte ich, sprich state kann nur Werte von signalstate bekommen,> und die Werte im enum möchte ich nicht aufrufen indem ich schreibe> "stop" usw.. sondern nur wenn ich den Enumnamen davorschreibe damit ich> auch nur das stop habe und nicht ein stop aus einem anderen enum.>> Gehts? Gehts nicht? Bitte um Hilfe!>>> P.S. Ich finde die Fehlermeldung dabei geil:> request for member 'stop' in something not a structure or union>> In "something". ~
Scoped enums gibt es nur in C++.
MOBA 2. schrieb:> P.S. Ich finde die Fehlermeldung dabei geil:> request for member 'stop' in something not a structure or union>> In "something". ~
Naja, something ist der Name Deiner Variablen!
Wilhelm M. schrieb:> MOBA 2. schrieb:>>> P.S. Ich finde die Fehlermeldung dabei geil:>> request for member 'stop' in something not a structure or union>>>> In "something". ~>> Naja, something ist der Name Deiner Variablen!
Siehst du was was ich nicht sehe?! Ich habe keine Variablen namens
something.
Wilhelm M. schrieb:> MOBA 2. schrieb:>>> Sowas möchte ich, sprich state kann nur Werte von signalstate bekommen,>> und die Werte im enum möchte ich nicht aufrufen indem ich schreibe>> "stop" usw.. sondern nur wenn ich den Enumnamen davorschreibe damit ich>> auch nur das stop habe und nicht ein stop aus einem anderen enum.>>>> Gehts? Gehts nicht? Bitte um Hilfe!>>>>>> P.S. Ich finde die Fehlermeldung dabei geil:>> request for member 'stop' in something not a structure or union>>>> In "something". ~>> Scoped enums gibt es nur in C++.
Ja das weiß ich, dachte das geht auch in C, shit.
Gibt es einen Plan B das zu "faken"?!
MOBA 2. schrieb:> Ja das weiß ich, dachte das geht auch in C, shit.> Gibt es einen Plan B das zu "faken"?!
Warum benutzt Du nicht einfach eine neuere Version von C++? Wenn Du die
GCC installiert hast, dann ist höchstwahrscheinlich auch deren
C++-Compiler g++ bereits vorhanden. Dann kannst Du einfach:
1
enum States {
2
stop,
3
go,
4
slow1,
5
slow2,
6
ks1,
7
ks2,
8
ks3
9
};
10
11
States state = States::slow1;
(oder stattdessen "enum class States ...") verwenden, alles prima:
voller Nutzen, keine Kosten. Was spricht dagegen?
Sheeva P. schrieb:> MOBA 2. schrieb:>> Ja das weiß ich, dachte das geht auch in C, shit.>> Gibt es einen Plan B das zu "faken"?!>> Warum benutzt Du nicht einfach eine neuere Version von C++? Wenn Du die> GCC installiert hast, dann ist höchstwahrscheinlich auch deren> C++-Compiler g++ bereits vorhanden. Dann kannst Du einfach:>>
1
> enum States {
2
> stop,
3
> go,
4
> slow1,
5
> slow2,
6
> ks1,
7
> ks2,
8
> ks3
9
> };
10
>
11
> States state = States::slow1;
12
>
>> (oder stattdessen "enum class States ...") verwenden, alles prima:> voller Nutzen, keine Kosten. Was spricht dagegen?
Die obige (C++) enum Definition bzw. Verwendung ist keine scoped enum
Definition, d.h. eine folgende Definition etwa
1
enumStates1{
2
stop
3
};
führt zu einem Fehler, bei scoped enums eben nicht (daher scoped!).
Ausserdem gibt es eine impl. Typwandlung zwischen int und
unscoped-enums, was man ja gerade nicht will.
MOBA 2. schrieb:> Wilhelm M. schrieb:>> MOBA 2. schrieb:>>>>> P.S. Ich finde die Fehlermeldung dabei geil:>>> request for member 'stop' in something not a structure or union>>>>>> In "something". ~>>>> Naja, something ist der Name Deiner Variablen!>> Siehst du was was ich nicht sehe?! Ich habe keine Variablen namens> something.
Was nutzt Du für einen Compiler? Bzw. zeige den ganzen Quelltext oder
die originale Fehlermeldung.
MOBA 2. schrieb:> Gehts? Gehts nicht? Bitte um Hilfe!
Geht nicht. In der Regel behilft man sich, indem man allen Elementen
einen gemeinsamen Prefix gibt.
> P.S. Ich finde die Fehlermeldung dabei geil:> request for member 'stop' in something not a structure or union>> In "something". ~
Ja, und? Was stimmt damit denn nicht? Der Member-Operator geht
ausschließlich für den Zugriff auf Elemente von Strukturen und Unions.
Links vom Punkt steht aber etwas, das weder eine Struktur, noch eine
Union ist (Oder eben wörtlich übersetzt: "something not a structure or
union"). Das ist also exakt das, was die Fehlermeldung sagt. Soll sie
dich jetzt noch darüber informieren, was das ist, was du da stattdessen
links vom Punkt hingeschrieben hast, oder was erwartest du?
MOBA 2. schrieb:> und die Werte im enum möchte ich nicht aufrufen indem ich schreibe> "stop" usw.. sondern nur wenn ich den Enumnamen davorschreibe damit ich> auch nur das stop habe und nicht ein stop aus einem anderen enum.
Das gibt es nicht in C. In C sind alle enum-Varianten in einem
gemeinsamen Namensraum abgelegt.
Du kannst also nicht "stop" in zwei unterschiedlichen enums verwenden,
selbst wenn beide Varianten den gleichen Wert hätten.
Rufus Τ. F. schrieb:> MOBA 2. schrieb:>> und die Werte im enum möchte ich nicht aufrufen indem ich schreibe>> "stop" usw.. sondern nur wenn ich den Enumnamen davorschreibe damit ich>> auch nur das stop habe und nicht ein stop aus einem anderen enum.>> Das gibt es nicht in C. In C sind alle enum-Varianten in einem> gemeinsamen Namensraum abgelegt.>> Du kannst also nicht "stop" in zwei unterschiedlichen enums verwenden,> selbst wenn beide Varianten den gleichen Wert hätten.
Steht ja schon oben in meinem Beispiel...
MOBA 2. schrieb:> Kann man denn einen Enum in einen struct reinpacken?>> Das ist nur ein Tiny13, bei den kleinen wollte ich kein C++ nehmen.
Warum sollte das nicht gehen???? Und warum kein C++???
Wilhelm M. schrieb:> MOBA 2. schrieb:>> Kann man denn einen Enum in einen struct reinpacken?>>>> Das ist nur ein Tiny13, bei den kleinen wollte ich kein C++ nehmen.>> Warum sollte das nicht gehen???? Und warum kein C++???
Ne, die FW ist soweit fertig wollte die um eine Statemachine erweitern.
Jetzt nochmal alles umbauen möchte ich nicht machen.
1
typedefstruct_signalsystem
2
{
3
enum_states2
4
{
5
stop2,
6
go2
7
};
8
9
uint8_tstate;
10
}signalsystem_t;
11
12
signalsystem_tsignals;
So geht das zwar, weiß ich. Aber das aufrufen bleibt trzd. so:
signals.state = go2;
MOBA 2. schrieb:> Kann man denn einen Enum in einen struct reinpacken?
Ja, aber das löst kein Problem.
Wenn man bei C bleibt, wird man sich eine eigene sinnvolle Notation für
die einzelnen enum-Werte einfallen lassen müssen.
Eine Variante ist die Verwendung des Enum-Namens als Präfix:
1
enum_states
2
{
3
_states_stop,
4
_states_go,
5
_states_slow1,
6
_states_slow2,
7
_states_ks1,
8
_states_ks2,
9
_states_ks3
10
}signalstate;
Du solltest allerding auf den führenden Unterstrich verzichten. Der ist
laut C-Standard reserviert.
Rufus Τ. F. schrieb:> MOBA 2. schrieb:>> Kann man denn einen Enum in einen struct reinpacken?>> Ja, aber das löst kein Problem.>> Wenn man bei C bleibt, wird man sich eine eigene sinnvolle Notation für> die einzelnen enum-Werte einfallen lassen müssen.>> Eine Variante ist die Verwendung des Enum-Namens als Präfix:>>
1
>enum_states
2
>{
3
>_states_stop,
4
>_states_go,
5
>_states_slow1,
6
>_states_slow2,
7
>_states_ks1,
8
>_states_ks2,
9
>_states_ks3
10
>}signalstate;
11
>
>> Du solltest allerding auf den führenden Unterstrich verzichten. Der ist> laut C-Standard reserviert.
Jo, so habe ich es auch jetzt gemacht.
Das enum signalstates genannt und den als prefix genommen.
Vielleicht ist es ja schlechter Stil, da bin ich mir selbst unsicher.
Aber ich vergebe mittlerweile enums überhaupt gar keine Namen mehr,
sondern nur den Typen. Also sowas wie
1
enum
2
{
3
stop,
4
go,
5
slow1,
6
slow2,
7
ks1,
8
ks2,
9
ks3
10
}signalstate_t;
Ich wüsste nicht was ich mit dem Namen des Enums je gemacht hätte. Wozu
soll der eigentlich gut sein?
Konrad schrieb:
> Ich wüsste nicht was ich mit dem Namen des Enums je gemacht hätte. Wozu> soll der eigentlich gut sein?
Damit man schon in der typedef-Zeile (und nicht erst 42 Zeilen weiter
unten) sieht, was da eigentlich deklariert wird ;)
Konrad schrieb:> Ich wüsste nicht was ich mit dem Namen des Enums je gemacht hätte. Wozu> soll der eigentlich gut sein?
Wenn man kein typedef verwendet, kann der enum nicht namenlos bleiben.
Das hier macht was anderes:
1
enumstates
2
{
3
states_stop,
4
states_go,
5
states_slow1,
6
states_slow2,
7
states_ks1,
8
states_ks2,
9
states_ks3
10
}signalstate;
Es definiert einen enum namens "states" und legt gleichzeitig eine
Variable dieses Typs an (signalstate).
Das kann man natürlich auch auftrennen:
MOBA 2. schrieb:> Wilhelm M. schrieb:>> MOBA 2. schrieb:>>> Kann man denn einen Enum in einen struct reinpacken?>>>>>> Das ist nur ein Tiny13, bei den kleinen wollte ich kein C++ nehmen.>>>> Warum sollte das nicht gehen???? Und warum kein C++???>>> Ne, die FW ist soweit fertig wollte die um eine Statemachine erweitern.> Jetzt nochmal alles umbauen möchte ich nicht machen.
Was solltest Du umbauen müssen?
Ich vermute einfach mal, dass Du bis auf Dein aktuelles Problemchen
Deinen Code
direkt mit einem C++ Compiler übersetzen kannst. Und dann suchst Du Dir
Features raus, die Du gerne hättest, eben z.B. scoped-enums.
Konrad schrieb:> Ich wüsste nicht was ich mit dem Namen des Enums je gemacht hätte. Wozu> soll der eigentlich gut sein?
Na damit er eben einen Namen hat. Bei
1
enum_states
hat man dann einen Typ mit Namen "enum _states".
Konrad schrieb:> typedef enum> {> stop,> go,> slow1,> slow2,> ks1,> ks2,> ks3> } signalstate_t;
Das ist halt eigentlich nicht der ursprünglich angedachte Weg gewesen.
Damit definierst du einen Typ, dem der Name fehlt und gibst ihm durch
das Typedef gleichzeitig einen "alternativen" Namen.
Rolf M. schrieb:> Damit definierst du einen Typ, dem der Name fehlt und gibst ihm durch> das Typedef gleichzeitig einen "alternativen" Namen.
Ist das schlecht?
Meine Argumentation ist: Gäbe ich bloß dem enum einen Namen, müsste ich
vor jeder Deklaration einer solchen Variablen nochmal explizit 'enum'
mit angeben. Aber in mindestens 99% der Fälle sagt der Typname alleine
schon alles aus, was da zu wissen interessant ist. Jedesmal explizit
anzugeben, dass es auch noch ein enum ist, ist uninteressanter
Singnatur-Clutter, der das Lesen des Codes eher behindert als fördert.
Bin ich aber einmal an dem Punkt, dass ich den enum in einen typedef
verkapsle, dann habe ich eigentlich für den enum-Namen keine Verwendung
mehr und lasse ihn daher weg.
Sowas wie
Konrad schrieb:> Rolf M. schrieb:>> Damit definierst du einen Typ, dem der Name fehlt und gibst ihm durch>> das Typedef gleichzeitig einen "alternativen" Namen.>> Ist das schlecht?
Nein, an sich nicht. Ich mag es irgendwie lieber mit eigenem Namen statt
typedef, da dann immer davor steht, um welche Art von Typ es sich
handelt.
> Meine Argumentation ist: Gäbe ich bloß dem enum einen Namen, müsste ich> vor jeder Deklaration einer solchen Variablen nochmal explizit 'enum'> mit angeben. Aber in mindestens 99% der Fälle sagt der Typname alleine> schon alles aus, was da zu wissen interessant ist. Jedesmal explizit> anzugeben, dass es auch noch ein enum ist, ist uninteressanter> Singnatur-Clutter, der das Lesen des Codes eher behindert als fördert.
Finde ich nicht. Es dokumentiert den Code eher. Aber das ist
Geschmackssache.
> Bin ich aber einmal an dem Punkt, dass ich den enum in einen typedef> verkapsle, dann habe ich eigentlich für den enum-Namen keine Verwendung> mehr und lasse ihn daher weg.
Bei enum ja. Bei struct ist das anders. Wenn man z.B. sowas wie eine
verkettete Liste machen will, bei der eine Instanz der Struktur wiederum
einen Zeiger auf den gleichen Typ enthält, braucht sie einen Namen, da
man den typedef-Namen innerhalb der Struktur selbst noch nicht verwenden
kann. Ein weiterer Fall sind reine Deklarationen. Wenn ich einen Typ
irgendwo nur deklariere, weil er für den Benutzer nicht direkt
zugänglich sein soll, dann funktioniert das auch nicht ohne Namen, denn
ich kann nicht schreiben:
1
typedefstructMeineStruct;
> Sowas wie> uint8_t state = signalstate.stop;> würde ich dann auch lieber durch> signalstate_t state = signalstate.stop; ersetzen.
Hmm, du willst das enum davor weg haben, aber schreibst ein _t dran? (*)
Und warum nur links, aber nicht rechts? Müsste es nicht
signalstate_t.stop (oder in C++-Manier signalstate_t::stop) heißen?
(*) Ich hab auch schon so Sachen gesehen, dass jemand ein typedef macht
und dann aber in den Namen reinkodiert, ob es ein enum, eine struct oder
sonstwas ist. Das finde ich dann allerdings wirklich albern.
Rolf M. schrieb:> Hmm, du willst das enum davor weg haben, aber schreibst ein _t dran?
Ja, damit habe ich auch lange gehadert. Aber ich bin einfach zu oft in
die Situation gerannt, dass ich für Typ und Instanz eigentlich hätte den
selben Namen nehmen wollen. Hier würde das zufällig gut gehen, mit
signalstate und state. So gesehen ist für mich dieser suffix _t weniger
die Information "ich bin ein Typ", sondern mehr die Freiheit eine
Variable konfliktfrei so zu bennen, wie es "natürlich" wirkt.
Und hätte ich dieses signalstate.stop nicht einem Zitat entnommen, dann
hätte es bei mir vermutlich SS_STOP gehießen. SS_ als Abkürzungsprefix
für alle Konstantennamen dieses Enums. Aber auch da bin ich mir nie so
ganz glücklich. Manchmal mache ich dann auch doch auch SIGNALSTATE_STOP.
MOBA 2. schrieb:> Wilhelm M. schrieb:>> MOBA 2. schrieb:>>> Das ist nur ein Tiny13, bei den kleinen wollte ich kein C++ nehmen.>>>> Warum sollte das nicht gehen???? Und warum kein C++???>> Ne, die FW ist soweit fertig wollte die um eine Statemachine erweitern.> Jetzt nochmal alles umbauen möchte ich nicht machen.
Wenn Du keine exotischen Sachen gemacht hast, ist es Deinem C-Code
wumpe, ob er mit einem C- oder einem C++-Compiler übersetzt wird. Das
kostet überhaupt nichts, und Du mußt auch nichts umbauen -- aber dafür
hast Du das gewünschte Feature und gut ist.
Wilhelm M. schrieb:> Sheeva P. schrieb:>> (oder stattdessen "enum class States ...") verwenden, alles prima:>> voller Nutzen, keine Kosten. Was spricht dagegen?>> Die obige (C++) enum Definition bzw. Verwendung ist keine scoped enum> Definition, d.h. eine folgende Definition etwa
Deswegen ja auch mein Hinweis auf "enum class States ...".
Sheeva P. schrieb:> MOBA 2. schrieb:>> Wilhelm M. schrieb:>>> MOBA 2. schrieb:>>>> Das ist nur ein Tiny13, bei den kleinen wollte ich kein C++ nehmen.>>>>>> Warum sollte das nicht gehen???? Und warum kein C++???>>>> Ne, die FW ist soweit fertig wollte die um eine Statemachine erweitern.>> Jetzt nochmal alles umbauen möchte ich nicht machen.>> Wenn Du keine exotischen Sachen gemacht hast, ist es Deinem C-Code> wumpe, ob er mit einem C- oder einem C++-Compiler übersetzt wird. Das> kostet überhaupt nichts, und Du mußt auch nichts umbauen -- aber dafür> hast Du das gewünschte Feature und gut ist.
Genau das hatte ich ihm oben ja auch nochmal geraten!
Natürlich gibt es Unterschiede: manche sind sehr subtil wie die
active-member-Regel bei unions in C++, andere offensichtlich wie etwa
das Attribut __flash in C.
Doch viele denken, sie müssten(!) den gesamten C++-Werkzeugkasten
nutzen. Aber das ist ja wie Du auch richtig sagst gar nicht nötig. Ich
kann wunderbar cherry-picking betreiben!
Sheeva P. schrieb:> Wenn Du keine exotischen Sachen gemacht hast, ist es Deinem C-Code> wumpe, ob er mit einem C- oder einem C++-Compiler übersetzt wird.
So ganz wumpe ist es aber nicht mehr wenn der C-Code dann auch noch
MISRA C oder C++ sein soll. Ich glaube nicht dass man dem Auditor
glaubhaft machen kann dass es ok ist den Code in C zu schreiben und
gegen MISRA zu checken und dann unterm Strich doch als C++ zu
übersetzen.
Da gibt es nämlich schon Unterschiede, und nicht nur dämliche Sachen wie
'42U' für MISRA C, aber '42u' für C++.
Eric B. schrieb:> Sheeva P. schrieb:>> Wenn Du keine exotischen Sachen gemacht hast, ist es Deinem C-Code>> wumpe, ob er mit einem C- oder einem C++-Compiler übersetzt wird.>> So ganz wumpe ist es aber nicht mehr wenn der C-Code dann auch noch> MISRA C oder C++ sein soll. Ich glaube nicht dass man dem Auditor> glaubhaft machen kann dass es ok ist den Code in C zu schreiben und> gegen MISRA zu checken und dann unterm Strich doch als C++ zu> übersetzen.> Da gibt es nämlich schon Unterschiede, und nicht nur dämliche Sachen wie> '42U' für MISRA C, aber '42u' für C++.
Wobei ich hoffe, dass der TO nicht aus einem Bereich kommt, in dem MISRA
eine Rolle spielt. Sonst hätte er hoffentlich diese Frage nicht gestellt
...
signalstate1=SIGNALSTATE_START;// Zuweisung als struct
20
21
// Abfrage:
22
if(signalstate1==SIGNALSTATE_START)// Geht nur bei manchen Compilern
23
printf("\Hello");
24
25
if(signalstate1.x==SIGNALSTATE_START.x)// Geht bei jedem Compiler!
26
printf("\Hello");
Dies lässt sich für Konfig.-Registerwerte von uC
auch mit bitfeldern kombinieren. Ist dann praktisch bei debuggen,
man muss dann keine hex-zahlen lesen... nehme ich immer her.
(zb bits 3...1 timermode: TIMER_MODE_UPCOUNTING)
Ich hoffe es trifft das was der Fragesteller sucht...
Btw: wer weis wie man das deklarieren für mehrere Werte (start, stop,
etc..) mit einem Makro vereinfachen könnte? Wäre hilfreich...
VG
Xaver schrieb:> Dies lässt sich für Konfig.-Registerwerte von uC> auch mit bitfeldern kombinieren. Ist dann praktisch bei debuggen,> man muss dann keine hex-zahlen lesen... nehme ich immer her.> (zb bits 3...1 timermode: TIMER_MODE_UPCOUNTING)
Zum Thema: bit-field in C:
"The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined."
Das verhindert die Benutzung von bit-fields für Register (es sei denn,
man setllt es per #pragma ein, etwa high-to-low).