Hallo, ich möchte als Switch-Variable ein Bitarray verwenden. Je nach gesetztem Bit soll ein bestimmter case durchlaufen werden. Jetzt stelle ich mir gerade die Frage ob das überhaupt funktioniert. Danke fürs Interesse
Ja so vielleicht oder?
1 | uint8_t variable = 0b00100000; |
2 | |
3 | switch (variable) { |
4 | case 0b00000001: |
5 | break; |
6 | case 0b00000010: |
7 | break; |
8 | // ...
|
9 | }
|
Und was machst du jetzt wenn mehr als ein Bit gesetzt ist? Ist das deine Frage oder was? ;)
Hallo, danke für die Antworten. Was ein Bitarray sein soll geht glaube ich aus dem Namen hervor. Es ist ein Array vom Typ Bool. Bsp: bool arr[5]; Ich wollte wissen ob das überhaupt geht, oder ob switch() generell immer eine ganzzahlige Variable erwartet. Danke
Hatte jetzt einen Compiler parat. switchtest.cpp(12): error C2450: switch-Ausdruck des Typs 'bool [5]' nicht zulässig. Ganzzahliger Ausdruck erwartet. Damit ist das geklärt.
>Was ein Bitarray sein soll geht glaube ich aus dem Namen hervor. >Es ist ein Array vom Typ Bool. Nur der Vollständigkeit halber: Ein bool hat normalerweise nicht ein Bit. Da heißt, wenn du acht bool erstellst, brauchst du meistens nicht ein Byte, sondern acht Byte (bzw. genaugenommen word).
Sorry, aber diese Aussage zweifle ich jetzt mal stark an. Ein Array vom Typ Bool mit beispielsweise 5 bit also z.B. bool arr[5]; sollte nach meinem Versändnis auch genau 5 bit lang sein und nicht länger oder kürzer.
Nein, denn viele Prozessoren haben 8,16,32 oder gar 64 Bit-Register, aber keine 1-Bit-Register, können somit mit einzelnen Bits nicht umgehen. Gleiches gilt für den Arbeitsspeicher. Somit ist ein C++ - 'bool' oft ein ganzes Byte, oder gar noch mehr.
Hansemann schrieb: > Sorry, aber diese Aussage zweifle ich jetzt mal stark an. > > Ein Array vom Typ Bool mit beispielsweise 5 bit also z.B. > > bool arr[5]; > > sollte nach meinem Versändnis auch genau 5 bit lang sein und nicht > länger oder kürzer. Falsch gedacht. bool ist mindestens so groß wie char.
Praktisch ein Byte (oder mehr) das zweckentfremdet wurde ? Es kennt trotzdem nur die Zustände 0 oder 1 ? Interessant. Das wußte ich wirklich noch nicht.
Hansemann schrieb: > Praktisch ein Byte (oder mehr) das zweckentfremdet wurde ? Es kennt > trotzdem nur die Zustände 0 oder 1 ? Richtig.
Hansemann schrieb: > Praktisch ein Byte (oder mehr) das zweckentfremdet wurde ? Es kennt > trotzdem nur die Zustände 0 oder 1 ? > > Interessant. Das wußte ich wirklich noch nicht. Dann merk dir. Das kleinste was es in C gibt, ist ein char. Definitionsgemäss hat ein char eine sizeof von 1. Kleiner als 1 geht nicht.
Hansemann schrieb: > Es kennt > trotzdem nur die Zustände 0 oder 1 ? Nein, man kann im Prinzip alle Zustände zuweisen, aber der Compiler verwendet eben nur true als '1' und false als '0'. Alles != 0 wird aber von if () als wahr erkannt. In C gibt es gar kein 'bool', nur 'char', und das ist eben ein byte, welchem man zB 0 und 1 zuweist. C++ kann da nicht 'mehr', es sieht nur hübscher aus mit 'bool'.
Der Weise schrieb: > Hansemann schrieb: >> Es kennt >> trotzdem nur die Zustände 0 oder 1 ? > Nein, man kann im Prinzip alle Zustände zuweisen, Doch. Du kannst zwar auch 42 zuweisen, aber in der Variable steht danach 1. Die Variable selber kennt also nur 0 und 1. Der Weise schrieb: > In C gibt es gar kein 'bool' Das stimmt schon seit einigen Jahren nicht mehr. Es gibt in stdbool.h ein bool als Alias für den integralen Typ _Bool, der auch obige Eigenschaft hat.
Das kann ich bestätigen. Ich benutze einen ANSI-C Compiler und dieser kennt definitiv den Typ Bool.
bool hat generell die länge eines char! Allerdings kannst Du ein sogenanntes Bitset verwenden..... Der Speicherbedarf davon ergibts sich dann bei den meisten Compilern als (Bitanzahl)/8 Byte.
Hier gabs einige Halbwahrheiten als Antwort. Diese stimmen zwar für die meisten C Implementierungen, aber eben nicht für alle. Bei solchen Fragen ist es meist am einfachsten, wenn man sich den C-Standard ansieht. Und zwar den, den man zur Programmierung verwendet. Ich kenne Firmen, bei denen wird noch nach C90 entwickelt. Da sind z.B. nicht mal Kommentare erlaubt, welche mit // beginnen, nur /* */. _Bool gibts ab C99. Bei Datentypen gibt der C-Standard der Compilerimplementierung einen relativ großen Spielraum. Kein Datentyp ist fix definiert, sondern gibt einen minimale Kapazität bzw. Bereich vor (C99 Kapitel 5.2.4.2.1 Sizes of integer types). z.B. C99 Kapitel 6.2.5: An object declared as _Bool is large enough to store the values 0 and 1. Was der Compiler daraus macht, ist nun seine Sache. Es gibt (wenige) Prozessoren, welche einen bitadressierbaren Speicherbereich haben. Für diese bietet es sich natürlich an, diesen zu verwenden. Der Compiler könnte aber auch Bitoperatoren auf einem _Bool verwenden, um die Daten effizient zu speichern. Natürlich auf Kosten der Laufzeit. Die meisten C-Implementierungen werden aber, wie hier erwähnt, einfach jeweils ein Byte verwenden. Aber auch hier kenne ich Projektkonfigurationen, bei denen 32 Bit für einen _Bool verwendet werden (Ich versteh auch nicht warum). Der Aussage, daß wenn man einer _Bool Variablen eine 42 zuweist, eine 1 rauskommt, hätte ich erstmal widersprochen. Da lag ich aber falsch, die Aussage stimmt. C99 6.3.1.2 Boolean type When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1. Auch wenn es sich so anhört, eigentlich wollte ich nicht klugscheißen. Ich habe einfach festgestellt, daß man stundenlang über das Verhalten eines C-Compilers diskutieren kann, aber nur im C-Standard steht, wie es sein sollte. Ich lag auch schon häufig falsch, obwohl ich mir sicher war. Nach langer Diskussion musste ich oft, nach einem Blick in den C-Standard, klein beigeben.
Ansonsten findest Du hier die Grammatik von C++ (ist für Deine Frage zu C nahezu identisch) http://www2.math.uni-wuppertal.de/~axel/skripte/oop/oopA.html => sowie Du Dir das vorstellst funktioniert es nicht. Du kannst bools allerdings sehr wohl platzsparend packen, und zwar mit einem Bit Field (sorry das ich oben irgendwo aus gewohnheit den Begriff Bit field verwendet habe).... Struct BlaBla { bool blabla1 : 1; bool blabla2 : 1; } etc.... Kannst Du auch über meherer Bits aufziehen, also z.B. struct IOAddr { bool IO : 1; int addr : 15; } das ganze noch in ne union gepackt kann man wunderbar die bits strukturell benamt rausziehen.... In http://www.9wy.net/onlinebook/CPrimerPlus5/ch15lev1sec4.html findest Du ein wunderbares beispiel wie man Bitfields in switch-Statements verwendet.... Hoffe das hilft!
> Auch wenn es sich so anhört, eigentlich wollte ich nicht klugscheißen. > Ich habe einfach festgestellt, daß man stundenlang über das Verhalten > eines C-Compilers diskutieren kann, aber nur im C-Standard steht, wie es > sein sollte. > Ich lag auch schon häufig falsch, obwohl ich mir sicher war. Nach langer > Diskussion musste ich oft, nach einem Blick in den C-Standard, klein > beigeben. Daran ist nichts überheblich... Und viele Sachen sind wie beispielsweise dangling else einfach nicht alle compilerimplementierungen gleich.... Und sowohl C'90 als auch C'99 sind nicht immer 100%ig umgesetzt in den einzelnen Compilern... Schlimmer wirds nur noch bei verwendung von C++... Wer hätte erwartet das: If (a && (a->b == 1) { .... völlig unterschiedlich abgearbeitet wird wenn der ||-operator überladen wird... Klar, ein Blick in die zugrundeliegenden Mechanismen macht eindeutig was passiert, aber aufs erste lesen kommt man nicht drauf.... Nicht überladen: a == NULL => Ergebniss steht fest => a->b == 1 wird nicht ausgewertet. Überladen: a && xx wird durch 2 Funktionsaufrufe ersetzt => Beide Statements werden abgearbeitet... Und a->b wird wenn a == NULL zum Problem....
Ein Struct Bitfield in Kombination mit einer Union würde ich in C nicht empfehlen! Wenn man MISRA beachten, dann ists auch nicht erlaubt. Gerade hier gibt es sehr viele Umsetzungsunterschiede (welche der C-Standard erlaubt). Wie genau die Daten einer Struct im Speicher abgelegt werden, ist nicht eindeutig festgelegt. Da legen die Compiler gerne Füllbytes rein. Stichwort Padding. Ich bin leider gar nicht auf die ursprüngliche Frage eingegangen. Aber was soll im in diesem Switch Case passieren? Sollten unterschiedliche Reaktionen pro boolschem Wert passieren, also A) Wenn Bool_1 dann führe Code_1 aus Wenn Bool_2 dann führe Code_2 aus Wenn Bool_1 und Bool_2 dann führe Code_1 und Code_2 aus oder mit Kombinationen, also B) Wenn Bool_1 dann führe Code_1 aus Wenn Bool_2 dann führe Code_2 aus Wenn Bool_1 und Bool_2 dann führe Code_3 aus Für A) wäre ein Switch Case eher nicht geeignet. Für B) könnte man ggf. ein Lösung finden
Danke Uli. Mit dem C-Standard bin ich mittlerweile sehr vertraut. Aber ich muß zugeben, mit C++ kenn ich mich so gut wie gar nicht aus.
Martin schrieb: > Bei Datentypen gibt der C-Standard der Compilerimplementierung einen > relativ großen Spielraum. Kein Datentyp ist fix definiert, sondern gibt > einen minimale Kapazität bzw. Bereich vor (C99 Kapitel 5.2.4.2.1 Sizes > of integer types). > z.B. C99 Kapitel 6.2.5: An object declared as _Bool is large enough to > store the values 0 and 1. > Was der Compiler daraus macht, ist nun seine Sache. > Es gibt (wenige) Prozessoren, welche einen bitadressierbaren > Speicherbereich haben. Für diese bietet es sich natürlich an, diesen zu > verwenden. Und was soll sizeof(_Bool) in dem Fall sein? Martin schrieb: > Der Compiler könnte aber auch Bitoperatoren auf einem _Bool verwenden, > um die Daten effizient zu speichern. Natürlich auf Kosten der Laufzeit. Und wie sieht dann ein Pointer auf _Bool aus? Es gibt eben halt noch ein paar mehr Dinge zu bedenken, als nur "large enough to store the values 0 and 1". Martin schrieb: > Aber auch hier kenne ich > Projektkonfigurationen, bei denen 32 Bit für einen _Bool verwendet > werden (Ich versteh auch nicht warum). Wie viel Bit hat ein char dort? sizeof(char) ist immer 1, egal wie viel Bit es hat. Und kleiner als 1 geht nun mal nicht, also ist auch ein _Bool immer mindestens so groß wie ein char.
Stefan Ernst schrieb: > Wie viel Bit hat ein char dort? Das hängt von der Prozessorarchitektur ab. Laut Standard ist ein char immer ein Byte groß. Wieviel Bits jetzt in einem Byte stecken, ist architekturabhängig. Der Standard sagt lediglich, dass es mindestens acht sein müssen. Christian
Christian Gudrian schrieb: > Stefan Ernst schrieb: > >> Wie viel Bit hat ein char dort? > > Das hängt von der Prozessorarchitektur ab. Laut Standard ist ein char > immer ein Byte groß. Vorsicht, der C-Standard versteht unter einem 'Byte' etwas anderes als ein Computerarchitekt. Für den C-Standard ist ein Byte die kleinste adressierbare Speichereinheit. Und wenn dieses Byte aus 16 Bit besteht, dann ist das im Sinne des C-Standards ein Byte. Für jemanden aber der sich mit Speicherbausteinen rumschlägt sind das 2 Byte. Ob dieser Unterscheidung kommen regelmässig Missverständnisse zu Stande.
Uli Trautenberg schrieb: > bool hat generell die länge eines char! das ist falsch Martin schrieb: > Aber auch hier kenne ich > Projektkonfigurationen, bei denen 32 Bit für einen _Bool verwendet > werden (Ich versteh auch nicht warum). Manche Processoren können nur vielfache ihrer natürloichen Wortbreite adressieren. dh. wenn diese 4 ist und du ein uint8_t hast, besteht ein Zugriff auf dieses uint8 immer darin, eine 32bit Variable auszulesen und den Rest auszumaskieren. was also mindestens immer 2 Befehle sind. wahrscheinlich kommt das Laden der Bitmaske und das zurechtschieben aber auch noch jeweils dazu. ein uint8_t i[16] braucht nur 4 Wörter, aber die Zugriffe auf i[0]-i[3] resultieren im Auslesen der selben Adresse und zurechtmaskieren und shiften.
Vlad Tepesch schrieb: > Uli Trautenberg schrieb: >> bool hat generell die länge eines char! > > das ist falsch > Das ist leider richtig! Wollte schreiben: In der Praxis mindestens die größe eines chars und auf allen mir bekannten Implementierungen die größe der kleinsten adressierbaren Einheit (meistens 1 Byte)
Stefan Ernst schrieb: > Martin schrieb: >> Bei Datentypen gibt der C-Standard der Compilerimplementierung einen >> relativ großen Spielraum. Kein Datentyp ist fix definiert, sondern gibt >> einen minimale Kapazität bzw. Bereich vor (C99 Kapitel 5.2.4.2.1 Sizes >> of integer types). >> z.B. C99 Kapitel 6.2.5: An object declared as _Bool is large enough to >> store the values 0 and 1. >> Was der Compiler daraus macht, ist nun seine Sache. >> Es gibt (wenige) Prozessoren, welche einen bitadressierbaren >> Speicherbereich haben. Für diese bietet es sich natürlich an, diesen zu >> verwenden. > > Und was soll sizeof(_Bool) in dem Fall sein? > Dazu gibt der C-Standard nichts her. _Bool ist im C99 doch wirklich reingepriemelt. Wie in allen solchen Fällen führt dies zu einem "implementation definied behaviour". Gibts an mehreren Stellen. Bei sizeof ist dies sogar explizit erwähnt (C99 6.5.3.4 The value of the result is implementation-defined, and its type...). Dazu muß man dann das entsprechende Compilerhandbuch zur Hand nehmen. In dem Fall, der bitadressierbaren Speicherbereich sollte es gar nicht so schwer sein. Soweit ich weiß, verwenden diese Prozessoren für jedes Bit in diesem Speicherbereich eine eigene Adresse. Wobei allerdings an dieser Adresse wirklich nur ein Bit Speicherplatz zur Verfügung steht! Somit könnte man bei sizeof 1 zurückgeben und die weiteren Bedingungen an sizeof wären erfüllt. Vor allem sizeof(array) / sizeof(array[0]). Meine andere Aussage, daß der Compiler Bitoperatoren verwenden darf, um einen _Bool zu speichern, muß ich zurücknehmen. Damit kann man die sizeof Anforderungen nicht erfüllen. Wobei ich annehme, daß es für den Fall der bitadressierbaren Speicherbereiche, wirklich Umsetzungen gibt, für den zweiten nicht. > Martin schrieb: >> Der Compiler könnte aber auch Bitoperatoren auf einem _Bool verwenden, >> um die Daten effizient zu speichern. Natürlich auf Kosten der Laufzeit. > > Und wie sieht dann ein Pointer auf _Bool aus? > > Es gibt eben halt noch ein paar mehr Dinge zu bedenken, als nur "large > enough to store the values 0 and 1". > Wie schon erwähnt, da habe ich erst geschrieben, dann gedacht. Trotzdem kann ein _Bool kleiner sein als 8 Bit. > Martin schrieb: >> Aber auch hier kenne ich >> Projektkonfigurationen, bei denen 32 Bit für einen _Bool verwendet >> werden (Ich versteh auch nicht warum). > > Wie viel Bit hat ein char dort? > sizeof(char) ist immer 1, egal wie viel Bit es hat. Und kleiner als 1 > geht nun mal nicht, also ist auch ein _Bool immer mindestens so groß wie > ein char. Ein Char hat 1 Byte, 8 Bit. Bei Prozessoren mit bitadressierbieren Speicher (z.B. 8051 80515 80535 - hab aber persönlich keine Erfahrung damit) kann aber ein _Bool kleiner sein. Aber dort hat eben wirklich jedes Bit eine eigene Adresse. Der Aussage _Bool ist immer mindestens so groß wie ein char muß ich damit wirklich wiedersprechen. Sizeof kann natürlich minimal 1 zurückgeben. Es kommt halt noch aus Zeiten, in denen es in C noch kein _Bool gab. Aber im Speicher kann ein _Bool wirklich auch nur ein Bit sein (entsprechender Prozessor vorausgesetzt). Bei dem Projekt mit den 32bit _Bool liefert sizeof natürlich 4 zurück. Die Idee dahinter war, die native Speichergröße des 32bit-Prozessors für ein _Bool zu verwenden. Der Prozessor kann mit diesen nativen Variablen meist am effektivsten umgehen (darum bietet sich z.B. für eine Schleifenvariable int an). Im Fall von _Bool bezweifle ich aber, daß es dort effektiver wird.
Zurück zur eigentlichen Frage: Nein, switch/case lassen sich nur auf ganzzahlige Datentypen anwenden. Nicht auf Arrays, nicht auf floatingpoint-Werte und auch nicht auf Strings (die ja auch nur Arrays sind).
Karl Heinz Buchegger schrieb: > Ob dieser Unterscheidung kommen regelmässig Missverständnisse zu Stande. Und deshalb danke ich Dir für die explizite Klarstellung. Und der Vollständigkeit halber: die korrekte, unmissverständliche Bezeichnung für eine Gruppe von acht Bits lautet "Oktett". Christian
Martin schrieb: > Ein Char hat 1 Byte, 8 Bit. Mindestens 8 Bit. Es können mehr sein, auch wenn einem das in der Realität nur selten begegnet. Christian
Christian Gudrian schrieb: > Martin schrieb: > >> Ein Char hat 1 Byte, 8 Bit. > > Mindestens 8 Bit. Es können mehr sein, auch wenn einem das in der > Realität nur selten begegnet. > > Christian Stimmt natürlich!
Man kann switch aber auf einzelne Elemente des Arays anwenden und die switch Anweisung dann verschachteln. char b[5]; switch(b[0]) { case 0: switch(b[1]) { case 1: switch(b[2]) { case 0b00010100 : break; case 0b00010101 : break; } break; case 2: switch(b[2]) { case 0b00010100 : break; case 0b00010101 : break; } break; } break; case 1: switch(b[1]) { case 3: switch(b[2]) { case 0b00010100 : break; case 0b00010101 : break; } break; case 9: switch(b[2]) { case 0b00010100 : break; case 0b00010101 : break; } break; } break; }
Uwe schrieb: > Man kann switch aber auf einzelne Elemente des Arays anwenden Vorausgesetzt, daß diese Elemente wiederum ganzzahlige Datentypen sind. Im übrigen ist die binäre Schreibweise mit 0b-Präfix nicht im C-Standard enthalten. So etwas ist eine proprietäre Compilererweiterung und man sollte sich den Gebrauch schleunigstens wieder abgewöhnen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.