Hallo, Wie kann ih in C für eclipse GCC eine Variable mit einem Bit Definieren? Selbes wie mache ich das bei einem Byte? Sorry bin noch Anfänger in C und habe zuvor viel mit Basic gemacht.
1 | #include <stdbool.h> |
2 | |
3 | int main () { |
4 | bool x = true; |
5 | x = false; |
6 | }
|
Tatsächlich wird "bool" aber immer 8 Bits Speicher belegen; richtige 1-Bit-Variablen gibt es auf heutigen Prozessoren nicht.
habichvergessen schrieb: > Hallo, > > Wie kann ih in C für eclipse GCC eine Variable mit einem Bit Definieren? > Selbes wie mache ich das bei einem Byte? > Nimm einfach unsigned char - für dein Byte und wenn Du mehrere „Bit - Variablen” hast, kannst Du die auch in einem unsigned char unterbringen C hat genügend Operatoren um bitweise vernünftig damit arbeiten zu können.
Dr. Sommer schrieb: > Tatsächlich wird "bool" aber immer 8 Bits Speicher belegen; richtige > 1-Bit-Variablen gibt es auf heutigen Prozessoren nicht. beides Falsch bool ist int und damit meist 16 Bit es gibt auch echt 1Bit in Hardware z.B bei Infineon Tricore und auch anderen
Volle schrieb: > beides Falsch Soso: https://ideone.com/LTWJKV Volle schrieb: > es gibt auch echt 1Bit in Hardware > z.B bei Infineon Tricore und auch anderen Ok, die lassen sich in C nicht standardkonform abbilden, da in C die Variablengröße immer ein Vielfaches von char ist, und char ist mind. 8 bit.
Dafür hat NXP die BitBanding Area. Da bekommt man dann tatsächliche Bitvariableb
Volle schrieb: > Dr. Sommer schrieb: >> Tatsächlich wird "bool" aber immer 8 Bits Speicher belegen; richtige >> 1-Bit-Variablen gibt es auf heutigen Prozessoren nicht. > > beides Falsch > > bool ist int und damit meist 16 Bit > Auch falsch, Datentypen sind immer vom Compiler abhängig, auch bool Soweit ich mich an Programmieren Vorlesung erinnere ist tatsächlich bei C nicht mal die 1 Byte Größe von char garantiert. C Spezifikation garantiert mindestgrößen für Variablen: char: mindestens 8 Bit short: mindestens so groß wie char int mindestens so groß wie short Ich meine beim Microsoft Visual C Compiler mal die Einstellung gesehen zu haben: Char width: 1 oder 2 Byte. will man die exakten Größen von Variablen wissen, dann muss man die Dokumentation des Compilers durchlesen. Dort sind die exakt spezifiziert. Alternative: stdint.h verwenden. Wobei eine Dokumentation eines Compilers finde ich persönlich ziemlich interessant. Man möge mich steinigen falls ich falsch liege.
hl. Stephanus schrieb: > Soweit ich mich an Programmieren Vorlesung erinnere ist tatsächlich bei > C nicht mal die 1 Byte Größe von char garantiert. "3.7.1 1 character single-byte character 〈C〉 bit representation that fits in a byte" > short: mindestens so groß wie char Mindestens -32767..+32767
Dr. Sommer schrieb: > Tatsächlich wird "bool" aber immer 8 Bits Speicher belegen; richtige > 1-Bit-Variablen gibt es auf heutigen Prozessoren nicht. Es gibt Flags, die der Compiler (manchmal) dafür nutzen kann. Das T-Flag beim AVR ist im Prinzip ein 1-Bit-Register. Der SDCC nutzt sowas auf manchen Architekturen, wenn die Lebenszeit eines Bools hinreichend kurz ist. Walter K. schrieb: > Nimm einfach unsigned char Das war mal ein sinnvoller Rat, ist es heutzutage nicht mehr. Wenn man genug Bits hat, dann ist "unsigned int" (in jedem Fall auf dem Target effizient, was für char nicht gelten muss) die bessere Wahl. Echte 1-Bit-Variablen gibt es in C nur in Form von "bool" (bzw. "_Bool") und als Teil eines Bitfeldes. Volle schrieb: > bool ist int Das ist schlichtweg falsch. bool ist _Bool, und _Bool ist, was der Compiler draus macht. Der darf auch mehrere bools in ein Byte packen. Dr. Sommer schrieb: > Ok, die lassen sich in C nicht standardkonform abbilden, da in C die > Variablengröße immer ein Vielfaches von char ist, und char ist mind. 8 > bit. Gilt das auch für bool? Denn das ist per Definition eine Variable, die nur genau zwei Zustände annehmen kann... hl. Stephanus schrieb: > Soweit ich mich an Programmieren Vorlesung erinnere ist tatsächlich bei > C nicht mal die 1 Byte Größe von char garantiert. In C gibt es überhaupt keine 8-Bit-Bytes. Ein char ist aber genau CHAR_BITS Bits groß, und CHAR_BITS muss nicht gleich 8 sein. Im Gegensatz zu C erfordert POSIX allerdings, dass CHAR_BITS gleich 8 ist, obwohl das m.W. nicht explizit aufgeschrieben ist.
:
Bearbeitet durch User
S. R. schrieb: > In C gibt es überhaupt keine Bytes. Im Standard gibt es diesen Begriff. "byte addressable unit of data storage large enough to hold any member of the basic character set of the execution environment" > Im Gegensatz zu C erfordert POSIX allerdings, dass CHAR_BITS gleich 8 > ist, obwohl das m.W. nicht explizit aufgeschrieben ist. Im C Standard sind es mindestens 8 Bits.
:
Bearbeitet durch User
A. K. schrieb: > Im Standard gibt es diesen Begriff. Stimmt, ich hatte das korrigiert, während du schon geantwortet hast. :-) A. K. schrieb: > Im C Standard sind es mindestens 8 Bits. Stimmt auch, allerdings lässt sich mit einem Wert ungleich (größer) 8 kein POSIX implementieren. War auch eher als Anmerkung gedacht. :-)
Volle schrieb: > bool ist int und damit meist 16 Bit "bool" existiert nur als Makro für "_Bool". "While the number of bits in a _Bool object is at least CHAR_BIT, the width (number of sign and value bits) of a _Bool may be just 1 bit."
A. K. schrieb: > hl. Stephanus schrieb: > >> short: mindestens so groß wie char > > Mindestens -32767..+32767 Ok, ich gebe mich geschlagen, Asche auf mein Haupt
Stefan schrieb: > Dafür hat NXP die BitBanding Area. Das ist eine herstellerunabhängige Eigenschaft von ARM Cores. Abgesehen vom M0 (und evtl M1) hat das m.W. jeder Cortex Mx. Bei Bitbanding im RAM aber drauf achten, dass für den Compiler normale Bytes und darin enthaltene Bitbanding-Bits getrennte Objekte sind. Er weiss nicht, dass sie per Hardware gekoppelt sind. Zugriffsoptimierung kann ggf einen Streich spielen.
:
Bearbeitet durch User
S. R. schrieb: > Echte 1-Bit-Variablen gibt es in C nur in Form von "bool" (bzw. "_Bool") > und als Teil eines Bitfeldes. Der oben zitierten Fussnote im Standard folgend kann _Bool eine 1-Bit Variable sein, die 8 Bits Platz benötigt. ;-)
S. R. schrieb: >> Walter K. schrieb: >> Nimm einfach unsigned char > > Das war mal ein sinnvoller Rat, ist es heutzutage nicht mehr. Wenn man > genug Bits hat, dann ist "unsigned int" (in jedem Fall auf dem Target > effizient, was für char nicht gelten muss) die bessere Wahl. Weshalb sollte ein unsigned int heute effizienter als ein unsigned char sein? Jetzt bitte keinen Fall konstruieren, bei dem man mehrere unsigned char - statt einem unsigned int braucht ;-)
Walter K. schrieb: > Weshalb sollte ein unsigned int heute effizienter als ein unsigned char > sein? Weil viele Prozessoren in Registern keine Bytes verarbeiten können. Das kann zu Anpassungsoperationen führen, die den Aufwand gegenüber "int" erhöhen. Deshalb gibt es Typen wie uint_fast8_t, die je nach Prozessor als Bytes oder grösser implementiert werden.
:
Bearbeitet durch User
Es nennt sich Integer Promotion (s. ANSI Standard) und es bedeutet, dass jede mathematische oder logische Operation immer auf mindestens integer-breite durchgeführt werde, auf dem RISC wie Arm ist es immer so, auf dem x86 muss es nicht sein. Und wenn man Byte als Operand hat, wird es vor der Operation erst nach integer gecastet, was die Zeit kostet ....
Beitrag #5524788 wurde vom Autor gelöscht.
Mix schrieb: > Es nennt sich Integer Promotion (s. ANSI Standard) und es bedeutet, dass > jede mathematische oder logische Operation immer auf mindestens > integer-breite durchgeführt werde, Es bedeutet, dass das Ergebnis dem entsprechen muss. Die tatsächliche Operation muss nicht in dieser Form erfolgen, wenn das gleiche Ergebnis rauskommmt. Nur muss der Compiler sich bei RISCs entscheiden, ob bei uchar Werten in Registern entweder der Rest des Registers immer 0 enthält, oder beliebig ist. Je nachdem kann es dann passieren, dass bei manchen Operationen vorher oder nachher maskiert werden muss.
Aber die Frage des TE war doch: „...Wie kann ih in C für eclipse GCC eine Variable mit einem Bit Definieren? Selbes wie mache ich das bei einem Byte?...“ Was soll der nun mit Integer Promotion und schnellen oder gar schnellsten C99 Datentypen wie uint_fastx_t anfangen?
Nimm einfach für beides den Datentyp Char. Wenn du char als "Bit" verwenden willst, dann heißt das in C im Umkehrschluss, dass eine null in der char-Variable FALSE bedeutet und alles, was ungleich null ist, bedeutet TRUE. Willst du irgendwo im Programm in dein "Bit" den Status TRUE speichern, dann schreib einfach fürs Verständnis eine 1 rein, bei FALSE eine null. Bei einer Abfrage auf 1 kannst du dann einfach: if (variable) ... schreiben. Bei einer Abfrage auf 0 dann if (variable == 0) Das doppelte Istgleich ist wichtig!
Walter K. schrieb: > Was soll der nun mit Integer Promotion und schnellen oder gar > schnellsten C99 Datentypen wie uint_fastx_t anfangen? Je nachdem was man mit den Booleans macht. Immerhin kann man die nicht nur setzen/löschen/abfragen, sondern auch damit rechnen. Sowas wie _Bool x; ... x << n ...
:
Bearbeitet durch User
Patrick schrieb: > if (variable == 0) > Das doppelte Istgleich ist wichtig! if (variable) if (!variable) tuts an Stelle von Vergleichsoperationen auch. Grad bei _Bool.
:
Bearbeitet durch User
Patrick schrieb: > Nimm einfach für beides den Datentyp Char. Wie bereits erwähnt, ist "char" für einen booleanschen Datentypen nicht optimal, insbesondere nicht auf dem gegebenen STM32 (siehe Titel). Nimm entweder "unsigned int", "bool", oder ein Bitfeld.
habichvergessen schrieb: > Wie kann ih in C für eclipse GCC eine Variable mit einem Bit Definieren? > Selbes wie mache ich das bei einem Byte? Bit: bool Byte: uint8_t
Ich finde es immer wieder geil, wenn ein Anfänger eine Anfängerfrage stellt, und darauf überhaupt nicht eingegangen wird, sondern die erste Antwort zu dem Thema auf akademischem Niveau zerpflückt wird... Nutzen für den Fragesteller ist weniger als Null, denn der ist jetzt noch verwirrter und hat nun Angst vor dem Thema, weil sich ja schon die selbsternannten "Experten" nicht einig sind....
Na gut, noch ein Versuch zum ursprünglichen Thema zu kommen : einzelne Bits kann man in C innerhalb von Strukturen anordnen :
1 | struct { |
2 | unsigned int buhl:1; |
3 | } lieblingsvariable; |
fop schrieb: > Na gut, noch ein Versuch zum ursprünglichen Thema zu kommen : > einzelne Bits kann man in C innerhalb von Strukturen anordnen : > >
1 | > struct { |
2 | > unsigned int buhl:1; |
3 | > } lieblingsvariable; |
4 | >
|
Wobei die struct ganze Bytes belegt, man also nur bei Verwendung mehrerer solcher Bits wirklich Speicher spart: struct s { bool b1 : 1; bool b2 : 1; unsigned int i1 : 1; signed int s1 : 1; unsigned int i2 : 4; } würde wohl 1 Byte belegen. Philipp
Klugscheisser schrieb: > Ich finde es immer wieder geil, wenn ein Anfänger eine Anfängerfrage > stellt, und darauf überhaupt nicht eingegangen wird, sondern die erste > Antwort zu dem Thema auf akademischem Niveau zerpflückt wird... Ist es besser, das zu beklagen, ohne selbst eine Antwort auf die Frage parat zu haben?
Philipp Klaus K. schrieb: > Wobei die struct ganze Bytes belegt, man also nur bei Verwendung > mehrerer solcher Bits wirklich Speicher spart: > > struct s > { > bool b1 : 1; > bool b2 : 1; > unsigned int i1 : 1; > signed int s1 : 1; > unsigned int i2 : 4; > } > > würde wohl 1 Byte belegen. Allerdings ist der Zugriff darauf meistens weniger performant, als auf "normale" bool Variablen. Ich würde das nur machen, wenn das Sparen von Speicherplatz wirklich notwendig ist.
Falls es ein STM32 sein sollte, der BitBanding unterstützt, dann könnte man damit jedes RAM-Bit ansprechen. In C wäre es ein uint32_t[], bei dem jedes Element 0 oder 1 wäre. Packt die bool's maximal und kommt ohne Bit-Schiebereien aus. Wobei z.B. ein M3, der das z.B. hätte, auch Bitfield-Befehle hat. Damit braucht man dann jeweils gerade man einen Befehl mehr für einen Zugriff.
:
Bearbeitet durch User
Carl D. schrieb: > Falls es ein STM32 sein sollte, der BitBanding unterstützt, dann könnte > man damit jedes RAM-Bit ansprechen. Was muss man in C beachten, damit der gcc dieses Feature nutzt?
Stefanus F. schrieb: > Carl D. schrieb: >> Falls es ein STM32 sein sollte, der BitBanding unterstützt, dann könnte >> man damit jedes RAM-Bit ansprechen. > > Was muss man in C beachten, damit der gcc dieses Feature nutzt? Man muß die BB-Adresse passend zur RAM-Adresse berechnen und darf nicht vergessen, daß der Compiler nichts davon weiß, daß die RAM-Variable nun volatile ist. Nicht unbedingt Anfänger-geeignet, besonders wenn es nicht auf des letzten 1/72tel-μs-Befehl ankommt ;-)
S. R. schrieb: > Das T-Flag beim AVR ist im Prinzip ein 1-Bit-Register. Das ist falsch. Das T-Flag ist nur ein Bit im 8-Bit-Register 'sreg'.
Philipp Klaus K. schrieb: > struct s > { > bool b1 : 1; > bool b2 : 1; > unsigned int i1 : 1; > signed int s1 : 1; > unsigned int i2 : 4; > } > > würde wohl 1 Byte belegen. In C ist die Größe weder vorhersagbar, noch ist das überhaupt erlaubt (trotzdem werden es die meisten Compiler in 2 oder 4 Byte umsetzen.)
Stefanus F. schrieb: > Carl D. schrieb: >> Nicht unbedingt Anfänger-geeignet... > > Danke für die Erklärung. Das ging nicht gegen dich. Ich hatte da eher den TO, soweit er sich hier präsentiert hat, im Blick.
Carl D. schrieb: >>> Nicht unbedingt Anfänger-geeignet... >> Danke für die Erklärung. > Das ging nicht gegen dich. Ich bin aber Anfänger. Abgesehen davon galt mein Dank der eigentlichen Erklärung. Nach der (und dem entsprechenden Artikel auf mikrocontroller.net) habe ich selbst schon beschlossen, es (vorläufig) nicht zu nutzen.
Erwin D. schrieb: >> Das T-Flag beim AVR ist im Prinzip ein 1-Bit-Register. > Das ist falsch. Das T-Flag ist nur ein Bit im 8-Bit-Register 'sreg'. Im Gegensatz zu allen anderen Bits in SREG ist es frei setz- und löschbar, hat keine Sonderbedeutung und ändert sich nicht als Nebeneffekt von Befehlen. Damit ist es für einen Compiler sinnvoll als 1 Bit-Register nutzbar. Darum "im Prinzip".
Achim S. schrieb: > In C ist die Größe weder vorhersagbar, noch ist das überhaupt erlaubt > (trotzdem werden es die meisten Compiler in 2 oder 4 Byte umsetzen.) Was soll da "nicht erlaubt" sein? Ich würde davon ausgehen, dass Compiler für Mikrocontroller hier üblicherweise nur ein Byte verwenden (zumindest der SDCC macht es so). Philipp
Philipp Klaus K. schrieb: > , dass Compiler für Mikrocontroller hier üblicherweise nur ein Byte > verwenden (zumindest der SDCC macht es so). Ja, es gibt immer Compiler, die sich um C einen Dreck scheren und für den beschränkten Anwendungsbereich "offensichtliche Fehler" beheben. Ja, in deinem Beispiel geht ein Anfänger sicher davon aus, dass alles in ein Byte passt und freut sich, wenn es auch so ist.
Achim S. schrieb: > Ja, es gibt immer Compiler, die sich um C einen Dreck scheren und für > den beschränkten Anwendungsbereich "offensichtliche Fehler" beheben. Ja, > in deinem Beispiel geht ein Anfänger sicher davon aus, dass alles in ein > Byte passt und freut sich, wenn es auch so ist. Ich weiß immer noch nicht, was du meinst. Das das Beispiel unvollständig ist (kein #include <stdbool.h>, kein Semikolon am Ende, es wird auch keine Variable angelegt), und so auch nicht von SDCC kompiliert würde? Wenn es für die Diskussion hilfreich ist, hier ein vollständiges, mit SDCC kompilierbares Beispiel, mit zwei Variablen (s1, s2), zu je einem Byte:
1 | #include <stdbool.h> |
2 | |
3 | struct s |
4 | {
|
5 | bool b1 : 1; |
6 | bool b2 : 1; |
7 | unsigned int i1 : 1; |
8 | signed int s1 : 1; |
9 | unsigned int i2 : 4; |
10 | };
|
11 | |
12 | struct s s1; |
13 | struct s s2; |
Philipp
Philipp Klaus K. schrieb: > Ich weiß immer noch nicht, was du meinst. Vermutlich, dass "implementation-defined" gleichbedeutend mit "da muss der Compiler aber einen Error werfen" bedeuten sollte. Was es nicht tut.
Stefanus F. schrieb: >> Falls es ein STM32 sein sollte, der BitBanding unterstützt, dann könnte >> man damit jedes RAM-Bit ansprechen. > > Was muss man in C beachten, damit der gcc dieses Feature nutzt? https://www.mikrocontroller.net/articles/ARM_Bitbanding
Ich hatte vor vielen Jahren mal einen Pascal Compiler für irgendeinen längst historischen µC, da konnte ma einzelne Bits so ansprechen: PORTA.0=HIGH PORTA.1=LOW Mit Variablen ging das genau so. Das könnte man meinetwegen gerne als Erweiterung in den C Standard aufnehmen.
Stefanus F. schrieb: > Das könnte man meinetwegen gerne als > Erweiterung in den C Standard aufnehmen. Man kann heute schon eine Union mit einem Bitfeld machen und Einzelbits in Variablen mit "var.b0" ansprechbar machen. Aber wie ich hier lernen durfte, ist das keine sinnvolle Lösung für Peripherieregister, weil damit immer ein RMW (read modify write)-Zugriff verbunden ist. "PORTA.0 = 1;" mag zwar schick sein, schreibt aber auch alle anderen Bits in "PORTA".
Stefanus F. schrieb: > Ich hatte vor vielen Jahren mal einen Pascal Compiler für irgendeinen > längst historischen µC, da konnte ma einzelne Bits so ansprechen: > > PORTA.0=HIGH > PORTA.1=LOW > > Mit Variablen ging das genau so. Das könnte man meinetwegen gerne als > Erweiterung in den C Standard aufnehmen. Das macht der SDCC z.B. für 8051 genau so. Es gibt das Keyword __bit, das den Typ "ein einziges Bit" repräsentiert. Mit "__bit __at 0x80 P0_0" kann man Bits auf auf bestimmte Adressen festlegen, z.B. hier P0.0 des 8051.
Stefanus F. schrieb: > Ich hatte vor vielen Jahren mal einen Pascal Compiler für irgendeinen > längst historischen µC, da konnte ma einzelne Bits so ansprechen: Ich hatte mal einen Pascal-Compiler! Einfach geschrieben auf %§$a000 => Pixel! Herrlich, Wahnsinn ;-)
S. R. schrieb: > Philipp Klaus K. schrieb: >> Ich weiß immer noch nicht, was du meinst. > > Vermutlich, dass "implementation-defined" gleichbedeutend mit "da muss > der Compiler aber einen Error werfen" bedeuten sollte. Was es nicht tut. Wobei ich im Beispiel nur ein "implementation-defined" sehe: Ob und wie viele Padding Bytes es am Ende der struct gibt, und damit wie groß sie insgesamt ist. Insbesondere darf der Compiler tatsächlich die ganze struct in ein einziges Byte packen. Aber korrektes C, das von einem C-Compiler akzeptiert werden sollte, ist es. Philipp
Philipp Klaus K. schrieb: > Ich weiß immer noch nicht, was du meinst. Mea Culpa. Ich dachte, C verlangt: 1) nur signed ODER unsigned innerhalb einer Struktur 2) Mindestgröße der Struktur = zugrundeliegender Basistyp (also 2/4-Bytes wenn ein (un)signed int dabei ist. Das ist aber wohl nur eine (erlaubte) Implementierung zweier Compiler hier. Jedenfalls finde ich nichts dazu im C-Standard. Darum ist alles, was ich schrieb, falsch. Und ich bin der letzte, der etwas gegen "implementation defined" hat. Von wegen nicht portabel oder so (dafür gibt's ja static asserts).
Achim S. schrieb: > Mea Culpa. ;-) Achim S. schrieb: > 1) nur signed ODER unsigned innerhalb einer Struktur Nein, das darf man beliebig mischen. Man darf auch andere Strukturen in einer Struktur haben, und da eine "struct" kein Vorzeichen hat, wäre so eine Forderung unsinnig. Wenn du einen Compiler hast, der so abgefahren ist, dass der das nicht akzeptiert, dann ist das kein C-Compiler. Achim S. schrieb: > 2) Mindestgröße der Struktur = zugrundeliegender Basistyp (also > 2/4-Bytes wenn ein (un)signed int dabei ist. Wenn ich in einer Struktur einen "int" speichere, dann muss die Struktur auch mindestens einen "int" groß sein. Wenn ich nur einen "char" drin speichere, muss sie nur "char" groß sein. Darf aber auch größer. Und ein Bitfeld mit 8 Einzelbits darf so groß sein wie ein Byte. Im (durchaus unportablen) Einsatz innerhalb einer Union macht man das ja absichtlich. :-)
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.