Switch/Case auf Array anwenden

Gast
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
Gast
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.
Gast
>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).
Gast
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.
Gast
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.
Gast
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 ?
>
> 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.
Gast
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.
Gast
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....
Gast
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
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.
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.
Gast
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.
Gast
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;

}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.