Forum: Compiler & IDEs boolsche Variable


von flyingwolf (Gast)


Lesenswert?

Hallo Leute.
Es gab mal sowas schönes wie boolsche Variable.
Man hat eine Variable, nennen wir sie "test" vom typ boolean
deklariert.
Dann konnte man test := true oder test := false setzen oder
zurücksetzen und mit if(test)  zb für einen Vergleich heranziehen.
Die Frage: Wenn ich ein Bit z.B. PORTD,PD7 so z.B. durch eine define
"vorbereiten", dass es genau so funktioniert, wie "test", wenn wir
mal davon ausgehen das die Zuweisung über = erfolgt und der Vergleich
über ==

von Christoph _. (chris)


Lesenswert?

In C geht das (soweit ich weiß) mangels Operatorüberladung nicht. Du
müsstest also auf (mehrere) Makros ausweichen.

In C++ könnte man zum Beispiel eine Klasse schreiben, die die von dir
verlangten Operatoren überlädt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Es gab mal sowas schönes wie boolsche Variable.

Gibt's in C99 übrigens auch.  Anders als in C++ (wo es ein
Standardtyp
ist) muss man in C #include <stdbool.h> machen, danach hat man den Typ
"bool" und die Werte "false" und "true" definiert.

> Die Frage: Wenn ich ein Bit z.B. PORTD,PD7 so z.B. durch eine define
> "vorbereiten", dass es genau so funktioniert, wie "test", wenn
wir
> mal davon ausgehen das die Zuweisung über = erfolgt und der
Vergleich
> über ==

Du meinst sowas?

#define PORTTEST (PIND & _BV(PD7))

...
  if (PORTTEST) {
    ...
  }

(Ich nehme mal an, du wolltest PIND testen und nicht PORTD. ;-)

von flyingwolf (Gast)


Lesenswert?

> (Ich nehme mal an, du wolltest PIND testen und nicht PORTD. ;-)

Ach ja, da war ja noch was. Ich gebe zu das Beispiel ist schlecht
gewählt. Ich dachte mir es wäre allgemeinverständlicher als
GPIOR2,GPIOR04.

mir schwebte etwas in der Art
 #define?? transmitter_online ??? (GPIOR2,GPIOR04)

if ("ankommende Daten ok") transmitter_online = true; (1) else
transmitter_online = false;

if (transmitter_online) { "Mach was "}

geht sowas und wenn ja, wie?

von Christoph _. (chris)


Lesenswert?

> geht sowas und wenn ja, wie?

Wie oben geschrieben, mit C geht das nicht.
Der Zuweisungsoperator hat in C eine genau festgelegte Bedeutung. Da es
keine "1-Bit-Variable" gibt (zumindest keinen Zeiger darauf), kann man
nur mit dem Zuweisungsoperator allein kein einzelnes Bit verändern.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Hier mal ein kleines Beispiel, wie es doch funktionieren könnte!
In wie weit das aber Portabel ist, kann ich nicht sagen. Die Idee kam
mir ganz spontan, als ich mich an einen anderen Thread erinnerte.
1
#include <avr/io.h>
2
#include <stdbool.h>
3
4
typedef struct
5
IOPort8Bit_s {
6
        unsigned char pin0:1;
7
        unsigned char pin1:1;
8
        unsigned char pin2:1;
9
        unsigned char pin3:1;
10
        unsigned char pin4:1;
11
        unsigned char pin5:1;
12
        unsigned char pin6:1;
13
        unsigned char pin7:1;
14
} IOPort8Bit_t;
15
16
IOPort8Bit_t *porta_mirr = (IOPort8Bit_t *)(&PORTA);
17
IOPort8Bit_t *pina_mirr = (IOPort8Bit_t *)(&PINA);
18
19
int
20
main(void)
21
{
22
        DDRA = 0xff;
23
24
        porta_mirr->pin1 = true;
25
        porta_mirr->pin2 = false;
26
        
27
        for(;;)
28
        {
29
                /* if(pina_mirr->pin1) or: */
30
                if(pina_mirr->pin1 == true)
31
                {
32
                        porta_mirr->pin0 ^= 1;
33
                }
34
        }
35
36
        /* NEVEREACHED */
37
        return 1;
38
}

von Andreas Fertl (Gast)


Lesenswert?

Du könntest doch auch eine Variablen einen Typedef machen.
typedef unsigned char Bool;      /* Boolean */
#define TRUE 1
#define FALSE !TRUE

So kannst du dann mit
Bool test;
eine "Boolsche" Variable deklarieren, die sich auch so verhält, nur
nicht 1 Bit belegt.

if (test)

Falls dann test==TRUE geht er rein, sonnst nicht.

Grüße Andreas

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Darum geht es ja nicht, er möchte definitiv nur ein Bit einer Variablen
manipulieren...

von ---- _. (quaddash)


Lesenswert?

Noch ein Detail am Rande. Ich glaube nicht, daß man so:
#define TRUE 1
#define FALSE !TRUE
True und False definieren sollte.

Besser ist:
#define TRUE (1==1)
#define FALSE (1==0)
somit wird TRUE und FALSE genauso definiert wie der Compiler selbst
intern auch die Werte darstellt.

von Andreas Fertl (Gast)


Lesenswert?

Hmm ok, falsch verstanden... :)

Wenn ich soetwas benötige verwende ich auch einen sturct, wie schon
oben beschrieben.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ist alles Quark. :-)

Unter C99 nimmt man eh' <stdbool.h> (und schreibt boot, true, und
false, also alles klein).

Ansonsten kannst du in de.comp.lang.c nachfragen, warum die
sinnvollsten Definitionen

#define TRUE 1
#define FALSE 0

heißen.

von flyingwolf (Gast)


Lesenswert?

< er möchte definitiv nur ein Bit einer Variablen
manipulieren...

Das ist nicht ganz richtig. Er möchte ein Bit eines Registers
abfragen oder manipulieren, aber nicht 3 Makros dafür benutzen
#define checktransmitter checkbit(
#define transmitter_online setbit(
#define transmitter_offline clearbit(

sondern nur transmitter dem Register ... zuweisen

und dann mit transmitter = true / transmitter = false oder
if(transmitter)

manipulieren

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Ok, gut, dann kommt jetzt die Preisfrage an Dich:

  Was passiert in dem von mir eingefügten Code?

von flyingwolf (Gast)


Lesenswert?

@
Hab ich gesagt, dass Dein Code schlecht, oder falsch ist?
Sieht klassse aus und von dem was ich so davon verstehe, wird er
sicherlich auch funktionieren. Ist zwar viel zu kompliziert für mich
aber bestimmt ok.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Was passiert in dem von mir eingefügten Code?

Er wird nicht garantiert funktionieren, weil du das volatile
vergessen hast. ;-)  IO-Register (die ja intern erstmal wie
Speicheradressen behandelt werden) müssen volatile sein.

Ansonsten ist ein bit field durchaus eine Möglichkeit dafür, ja.
Allerdings verliert der Compiler durch die zusätzlich eingefügten
Pointervariablen den Überblick, dass es sich um IO-Register handelt,
sodass er keine IO-Befehle mehr optimieren kann (IN, OUT, SBI, ...).
Besser ist daher
1
#define porta_mirr  ((volatile IOPort8Bit_t *)(&PORTA))
2
#define pina_mirr   ((volatile IOPort8Bit_t *)(&PINA))

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

>Hab ich gesagt, dass Dein Code schlecht, oder falsch ist?

Nein, hast Du nicht.
Bitte nicht gleich wieder unter die Decke gehen ;)

Ich passe den Code mal ein bißchen auf Deine spärlichen Angaben an,
damit Du das evtl. besser verstehst:
1
#include <avr/io.h>
2
#include <stdbool.h>
3
4
typedef struct
5
Register8Bit_s {
6
        unsigned char flag1:1;       /* irgendein flag      */
7
        unsigned char flag2:1;       /* irgendein flag      */
8
        unsigned char transmitter:1; /* transmitter ein/aus */
9
        unsigned char receiver:1;    /* receiver ein/aus    */
10
} Register8Bit_t;
11
12
Register8Bit_t reg;                  /* 'Register' anlegen  */
13
14
int
15
main(void)
16
{
17
        reg.transmitter = true;
18
        reg.receiver = false;
19
        
20
        for(;;)
21
        {       /* Endlosschleife */
22
                if(reg.flag1 == true)
23
                {       /* wenn flag1 gesetzt dann */
24
                        reg.flag2 ^= 1; /* toggle das andere */
25
                }
26
        }
27
28
        /* NEVEREACHED */
29
        return 1;
30
}

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Oha, wie peinlich!

Jörg hat natürlich völlig Recht. Ich habe das 'volatile' auch im
zweiten Code vergessen. Vermutlich würde im 2. Code einfach so ziemlich
alles wegoptimiert...

So wäre besser:
1
volatile Register8Bit_t reg;         /* 'Register' anlegen  */

von flyingwolf (Gast)


Lesenswert?

@OldBug
Das Beispiel ist mir schon in gewisser Weise klar.
Ich muss halt etwas mit dem Speicher geizen, darum möchte ich keine 8
Bit für einen boolschen Operanden verschwenden.
Natürlich kann ich das ganze Register so bitweise belegen, aber ich
komme mit den Structs nicht so gut klar und dann auch noch ein volatile
...
Das durchschaue ich nicht mehr und da inzwischen einfache if-Abfragen
den größten Wahnsinn anzetteln und mich in stundenlange Fehlersuche
verwickeln, will ich es nicht mit Dingen schmücken, die ich
anschließend nicht mehr kurz auflösen kann um Fehler einzugrenzen.
Ich werd es mir auf jeden Fall ausdrucken und für die nächste Version
vormerken, weil es zimlich gut aussieht,

nur...
wo ist der Punkt an dem ich "reg" dem GPIOR2 (das Register) zuweise?

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Ah, ok, ich wusste, daß ich was vergessen/übersehen hatte :-)

In Zeile 12:
Ersetze diese Zeile durch
1
#define reg ((volatile Register8Bit_t *)(&GPIOR2))

Das kostet Dich kein einziges Bit mehr Speicher.
'reg' kannst Du natürlich nach Lust und Laune umbenennen, so lange Du
 keinen bereits vergebenen 'Namen' auswählst.

von Stefan M. (Gast)


Lesenswert?

Zum Code von OldBug; ich kann mich noch daran erinnern, daß die
Reihenfolge der Bits abhängig vom Compiler ist. Die Reihenfolge ist im
C-Standard leider nicht festgelegt.

ciao, Stefan.

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
Noch kein Account? Hier anmelden.