ich hab ein programm, welches über enum den aktuellen menüzustand
auswählen soll. weiterschalten mach ich einfach per ++ - operator, was
zumindest keinen fehler wirft.
Was passiert jetzt aber, wenn ich über den letzten wert hinaus gehe?
wird dann automatisch auf den ersten gesetzt oder hab ich einen
überlauf?
> Was soll das für einen Programmiersprache sein?
Hmm, mal überlegen. GCC-Forum, ++-Operator...
Ich hab's: Delphi!
Zum Thema: In C ist ein enum nicht viel anderes als ein int.
Einer solchen Variablen kann ein Wert außerhalb des definierten
Bereichs zugewiesen werden. Geprüft wird da nichts.
In C++ ist ein Inkrement auf ein enum nur dann erlaubt wenn
der Operator explizit für diesen enum-Typ definiert wurde.
Auch folgendes geht in C++ nicht (in C dagegen schon):
Och nee, nicht wieder diese Sinnfragen.
Das hat überhaupt keinen Sinn. Es ist sozusagen vollkommen
sinnfrei. Diese Beispiel zeigt lediglich das der C-Compiler
hier (im Gegensatz zu C++) keine Typüberprüfung durchführt und
man einen enum wie einen int behandeln kann.
Aber das geht natürlich noch besser:
let wrote:
> ... Diese Beispiel zeigt lediglich das der C-Compiler> hier (im Gegensatz zu C++) keine Typüberprüfung durchführt
Simon K. wrote:
> gibt bei mir den Fehler:> 'main::uu' : no variable declared before '='>> mit dem MS Visual C++ 2008 Compiler.
was ja somit zu erwarten war...
BTW: der C-Compiler wird (vermutlich) eine Warnung ausgeben
Gruß
Roland
bei mir gabs keine warnung.
Heißt also, wenn ich nen ++ auf das enum mache, wirds evtl. irgendwann
über die Grenzen der enumerierung hinausgehen? Dann muss ich das wohl
abfangen :(
Langsam wirds eng auf dem 2313..
Weiß jemand, was ich da zur Optimierung alles tun kann? (okay- ist
eigentlich nen anderes topic wert..)
tecdroid wrote:
> Langsam wirds eng auf dem 2313..> Weiß jemand, was ich da zur Optimierung alles tun kann? (okay- ist> eigentlich nen anderes topic wert..)
Hallo,
also Deine Erwartungen sind etwas paradox: ob Du die Überlaufprüfung
selbst programmieren musst oder ob der Compiler dies für Dich tut ändert
nichts daran, daß eine gewisse Menge Code dafür notwendig sein wird.
Was sollte ein enum beim Überlauf tun ?
- Auf den 1. Wert springen ? Das kann an anderer Stelle genau falsch
sein
- Eine Bluescreen ausgeben ? Wäre korrekt, ist aber für einen uC
schwierig
Gruss,
Michael
Roland Praml wrote:
> Simon K. wrote:>> gibt bei mir den Fehler:>> 'main::uu' : no variable declared before '='>>>> mit dem MS Visual C++ 2008 Compiler.>> was ja somit zu erwarten war...
Klar, weil das Beispiel syntaktisch falsch ist, nicht weil es
sematischer Unfug ist.
Das Beispiel deklariert im enum-Namensraum einen enum mit dem
Namen "uu", aber keine Variable namens "uu".
Richtig muss es sein:
1
intmain(void)
2
{
3
enum{a,b,c}uu;
4
uu=1;
5
6
}
> BTW: der C-Compiler wird (vermutlich) eine Warnung ausgeben
Bevor du irgendwas mutmaßt, nimmst du besser einen Compiler. Der
GCC generiert eine Warnung, ja: "control reaches end of non-void
function". Sonst nichts. Hat er auch keinen Grund dazu. (Das
"warum?" ist schon genannt worden: in C ist, anders als in C++, ein
enum nur eine andere Form des Typs "int".)
Vielen Dank Herr Appelt für Deeeen Hinweis..
Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon
im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..
tecdroid wrote:
> Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon> im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..
Du wirst ja das enum nicht nur einfach so hinschreiben, sondern auch
verwenden, z.B. in einem Switch. Und dann setzt Du es im letzten Case
eben wieder auf 0, kostet 4 Byte.
Peter
tecdroid wrote:
> Vielen Dank Herr Appelt für Deeeen Hinweis..> Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon> im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..
Ach? Was meinst du, womit Compiler so kochen?
Das letzte Mal, als ich nachgesehen habe, war es jedenfalls auch nur
Wasser.
Jörg Wunsch wrote:
> tecdroid wrote:>> Vielen Dank Herr Appelt für Deeeen Hinweis..>> Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon>> im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..>> Ach? Was meinst du, womit Compiler so kochen?>> Das letzte Mal, als ich nachgesehen habe, war es jedenfalls auch nur> Wasser.
Ich glaube, du hast ihn hier missverstanden. Es geht nicht darum, dass
wenn der Compiler es macht, es effizienter wäre, sondern darum, dass es
dann im aktuellen Code schon enthalten wäre. Die aktuelle Größe des
Codes wäre also die Größe inklusive der Prüfung. Da man es aber selber
machen muss, kommt der Code zum aktuellen Code noch hinzu.
Stefan Ernst wrote:
> Da man es aber selber> machen muss, kommt der Code zum aktuellen Code noch hinzu.
Es wird trotzdem nicht mehr Binärcode, eher weniger (wie Peter
dargelegt hat -- weil man die Prüfung u. U. sowieso in seiner
Applikation bereits vornehmen muss).
Jörg Wunsch wrote:
> Stefan Ernst wrote:>>> Da man es aber selber>> machen muss, kommt der Code zum aktuellen Code noch hinzu.>> Es wird trotzdem nicht mehr Binärcode, eher weniger (wie Peter> dargelegt hat -- weil man die Prüfung u. U. sowieso in seiner> Applikation bereits vornehmen muss).
Du betrachtest es absolut, tecdroid meinte es aber relativ zur
aktuellen Größe. Und aktuell ist anscheinend keine "manuelle" Prüfung
drin.
Klar, es könnte natürlich auch sein, dass der Code durch hinzufügen der
Prüfung kleiner wird, "größer" dürfte aber deutlich wahrscheinlicher
sein.
Jörg Wunsch wrote:
> Richtig muss es sein:>> [c]> int main(void)> {> enum { a, b, c} uu;> uu = 1;>
Hallo,
eben nicht, logisch würde man schreiben:
[c]
int main(void)
{
enum { a, b, c} uu;
uu = a;
tecdroid write:
>Vielen Dank Herr Appelt für Deeeen Hinweis..>Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon>im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..>
Ich habe diese Diskussion zum Anlass genommen, mir ein blaues LCD zu
bestellen. Dann kann ich endlich zum enum-Überlauf den Bluescreen
auslösen.
Allerdings fehlt mit noch der dazu notwendige SW-Trap ;-)
Gruss,
Michael
Stefan Ernst wrote:
> Du betrachtest es absolut, tecdroid meinte es aber relativ zur> aktuellen Größe. Und aktuell ist anscheinend keine "manuelle" Prüfung> drin.
Der Punkt ist: um das gewünschte Überlaufverhalten zu erzeugen, muss
eine Prüfung drin sein. Wenn sie der Compiler selbst einfügt, dann
wäre es der gleiche Aufwand wie für den Programmierer (der selbst dann
vorgenommen werden müsste, wenn der Programmierer genau weiß, dass die
Prüfung nicht nötig ist).
Jörg Wunsch wrote:
> Der Punkt ist: um das gewünschte Überlaufverhalten zu erzeugen, /muss/> eine Prüfung drin sein. Wenn sie der Compiler selbst einfügt, dann> wäre es der gleiche Aufwand wie für den Programmierer (der selbst dann> vorgenommen werden müsste, wenn der Programmierer genau weiß, dass die> Prüfung nicht nötig ist).
Ja, das ist ja alles richtig.
Ich wollte dich doch nur darauf hinweisen (und ich bereue das längst),
dass du den Post von tecdroid falsch verstanden hast.
> Würde nur der compiler dies selbst tun, dann wäre ja diese logik schon> im binärcode enthalten- so gehen mal wieder 6-8 byte verloren..
Du hast das anscheinend so interpretiert:
"Wenn ich die Prüfungen von Hand machen muss, ist der Code größer, als
wenn der Compiler selber automatische Prüfungen einfüg."
Gemeint war aber (so sehe ich das jedenfalls):
"Wenn der Compiler keine automatischen Prüfungen einfügt, dann sind im
aktuellen Code auch noch gar keine Prüfungen enthalten. Ich muss sie
also noch selber hinzufügen, was den Code nochmal etwas größer macht."
"Größer" im Vergleich zum aktuellen Zustand (also ganz ohne Prüfungen),
nicht im Vergleich zur fiktiven Größe mit Compiler generierten
Prüfungen.
Stefan Ernst wrote:
> Gemeint war aber (so sehe ich das jedenfalls):
Ich sehe, was du meinst. Ob tecdroid das auch so meint, kann er uns
nächstes Jahr ja dann mal erklären...
Jörg Wunsch wrote:
> Der Punkt ist: um das gewünschte Überlaufverhalten zu erzeugen, /muss/> eine Prüfung drin sein. Wenn sie der Compiler selbst einfügt, dann> wäre es der gleiche Aufwand wie für den Programmierer (der selbst dann> vorgenommen werden müsste, wenn der Programmierer genau weiß, dass die> Prüfung nicht nötig ist).
Hallo,
jetzt hab ich kapiert, wie die Frage gemeint war....
Trotzdem wundert mich, wie man diese Frage so stellen kann ohne auch zu
erfragen, was der Compiler tatsächlich dann in dem Überlaufcode machen
soll.
Z.B. compiler fügt code hinzu, der von max auf min springt
enum {mo, di, mi, do, fr, sa, so} tag;
for(tag=mo;tag<=so;tag++)
ergäbe eine Endlosschleife.
Selbst wenn er hier eine Sonderbehandlung durchführen würde, bei einer
selbstprogrammierten Zählschleife mit while würde dies endlos laufen.
tag = mo;
while (tag <= so) tag++;
Ohne Overflow-Trap bzw. call einer optionalen Überlauf-Prozedur ist der
Compiler für einen bildschirmlosen uC völlig hilflos.
Gruss,
Michael
Was Andres: Aufm AVR macht "enum" insofern wenig Sinn als solches, weils
eben nen ganzen Integer verbraucht (wenn man nich den GCC generell auf
ne andre Wortbreite umstellt).
1
enumbla_e{
2
a,
3
b,
4
c
5
}
6
7
enumbla_evariable;/* <-- braucht i.d.R. vier Bytes */
Braucht auf dem AVR zwei Bytes (sizeof(int) == 2), aber man kann es
beim GCC (dessen Forum das ja hier ist) mittels __attribute__(packed)
auch auf ggf. ein Byte reduzieren.
Hallo,
interessante Fragen kommen mir da in den Sinn, geht nicht auch:
enum {a=1, b, c=5, d=7} x;
for (x=a, x<=d, x++) ....
Ist doch zur Laufzeit vemrutlich auch schwachfug, oder ?
Gruss,
Michael
Michael Appelt wrote:
> Ist doch zur Laufzeit vemrutlich auch schwachfug, oder ?
So ist es. Ein lückenhafter enum hat in C fast keinen Sinn (einziger
Unterschied zu lauter #defines ist, dass die Namen im Debugger
sichtbar sind). Das kontinuierliche Durchlaufen aller Werte eines
solchen enum ist aber auf jeden Fall Schwachfug: entweder haben die
Zwischenwerte auch einen Sinn, dann hätte man sie im enum mit
aufzählen sollen, oder die Zwischenwerte sind witzlos, dann hat die
Schleife aber keinen Nährwert.
Hallo,
Bindung der Konstanten des enum an die Variable wäre eine sinnvolle
Prüfung durch den Compiler. Also Wert aus dem enum tag kann nicht einer
variablen vom typ monat zugewiesen werden.
Nichmal das wird erkannt, oder ? Dafür mault doch sowieso ständig bei
Zuweisung von signed nach unsigned etc.
Gruss,
Michael
> Ein lückenhafter enum hat in C fast keinen Sinn
Vieleicht mal ein bisschen ueber den Tellerrand denken. Es gibt z.B.
auch genuegend Faelle, wo die Werte vorgegeben sind, man aber trotzdem
darueber iterieren moechte. Spontan fiele mir auch eine Menufunktion
ein, wo natuerlich nicht jede Zeile besetzt sein muss, etc, pp.
Michael Appelt wrote:
> Nichmal das wird erkannt, oder ?
Es darf in C nicht erkannt werden.
Der C-Standard beschreibt, dass eine Aufzählungskonstante den Typ
"int" besitzt, und dass enum-Typen grundsätzlich kompatible zum
Typ "int" sind.
In C++ funktionieren enums übrigens wirklich etwa so, wie sich viele
das hier vorstellen. In C sind sie nur eine Art Namen für Konstanten
vom Typ int.
> Dafür mault doch sowieso ständig bei> Zuweisung von signed nach unsigned etc.
Macht er gar nicht, er warnt nur dann, wenn die Vorzeichenhaftigkeit
des Zieltyps eines Zeigers verschieden ist.
Peter Stegemann wrote:
> Vieleicht mal ein bisschen ueber den Tellerrand denken. Es gibt z.B.> auch genuegend Faelle, wo die Werte vorgegeben sind, man aber trotzdem> darueber iterieren moechte. Spontan fiele mir auch eine Menufunktion> ein, wo natuerlich nicht jede Zeile besetzt sein muss, etc, pp.
Entweder hat das dazwischen aber einen semantischen Zweck (auch wenn
es nicht besetzt ist), dann sollte es einen Namen bekommen, oder aber
es hat keinen, dann brauch ich auch nicht erst drüber iterieren.
Mir fällt jedenfalls nichts ein, wo das Sinn haben könnte. In C++
kannste das schon irgendwie implementieren (da ja bereits geschrieben
wurde, dass du dann für die Implementierung deines ++-Operators selbst
zuständig bist), allerdings ist die Implementierung des Sprungs über
die Lücken dann ein Risiko, dass der ahnungslose Leser die Komplexität
der tatsächlich dahinterstehenden Operation nicht erwarten würde.
Hallo,
Ok, C++ ist inzwischen klar, da muss ich den Iterator selber
implementieren.
Für lückenhaft indizierung bietet sich an:
const int index (7) = {1, 3, 5, 7, 11, 13, 17}
for (int i=0; i<7; i++)
machwasmit(index(i));
In sowohl C als auch uCs sind ja für solche explizite Problemlösungen
ausgelegt.
Gruss,
Michael
Der Gedanke hinter C ist: "Vermeide unnütze Tests, damit der Code
schlank und sauschnell ist."
D.h. wann immer der Compiler nicht einschätzen kann, ob ein Test nötig
ist, überläßt er es dem Programmierer, die richtige und effektive Stelle
zu finden.
Bei dem Enum wäre die richtige Stelle für den Test in dem letzten Case
bzw. Default.
Soll der Compiler aber selber testen, müßte er es ja bei jeder Zuweisung
machen, was den Code erheblich vergrößern würde.
Es gibt auch Stellen, wo man direkt froh ist, daß C einen nicht mit
Tests gängelt, z.B. wenn man die Differenz zweier Zeitstempel bildet. Da
muß man dann ein Überlaufen zulassen, damit die Differenz gültig ist.
Peter
Jörg Wunsch wrote:
> Roland Praml wrote:>>> Simon K. wrote:>>> gibt bei mir den Fehler:>>> 'main::uu' : no variable declared before '='>>>>>> mit dem MS Visual C++ 2008 Compiler.>>>> was ja somit zu erwarten war...>> Klar, weil das Beispiel syntaktisch falsch ist, nicht weil es> sematischer Unfug ist.>> Das Beispiel deklariert im enum-Namensraum einen enum mit dem> Namen "uu", aber keine Variable namens "uu".
Danke. Darauf wollte ich hinaus. ;)