Forum: Compiler & IDEs int byteweise setzen


von Wolfgang H. (hastekene)


Lesenswert?

Hallo,
ich bin gerade auf der Suche nach einer Möglichkeit 16 Schalter bitweise 
zu setzen

hab die Schalter wie folgt angelegt

union
{
int byte;
struct
{
    unsigned Leds1:1;
  unsigned Leds2:1;
  unsigned Leds3:1;
  unsigned Leds4:1;
  unsigned Leds5:1;
  unsigned Leds6:1;
  unsigned Leds7:1;
  unsigned Leds8:1;
  unsigned Leds9:1;
  unsigned Leds10:1;
  unsigned Leds11:1;
  unsigned Leds12:1;
  unsigned Leds13:1;
  unsigned Leds14:1;

};
}volatile ledset;



wenn ich jetzt mit

ledset |=(1<<1);

darauf zugreife bekomme ich vom Compiler eine Fehlermeldung

../main.c:19: error: invalid operands to binary | (have 'union 
<anonymous>' and 'int')

Wenn jetzt jemand sagt "ist doch klar sind ja 2 Bytes "
hat er recht nur bin ich mit meiner Anwendung noch nicht weiter

Kann mir jemand eine andere Möglichkeit nennen da ich die Schalter in 
einer Schleife sowohl abfragen als auch setzen oder löschen möchte

im Voraus besten dank

Wolfgang

von Urks (Gast)


Lesenswert?

Entschuldige, aber was genau sagt diese Fehlermeldung?

>../main.c:19: error: invalid operands to binary | (have 'union <anonymous>' >and 
'int')

Ich übersetze sie mal ins Deutsche, falls das das Problem ist:

../main.c:19: Fehler: ungültige Operanden für binar | (hat 'union 
<anonym>' und 'int')

Das Problem ist erstmal nicht ob ein oder zwei Bytes. Das Problem ist, 
das der Compiler nicht weiss, welches der union Mitglieder er nun 
behandeln soll. Das eine, das Du mit "byte" benannt hast, ist es wohl 
nicht. Aber, nur mal angenommen, Du wolltest (<ironie> das ist natürlich 
völlig abwegig </ironie>) die struct irgendwie am Schlafittchen packen, 
sie wollte von Dir, das Du ihren Namen nennst, sonst will Sie Dein Kind, 
wie würdest Du sie wohl nennen?

von Wolfgang H. (hastekene)


Lesenswert?

Hallo,
was du da sagst gib ich dir recht, habe ich aber auch schon geschrieben
ändert aber nichts an der Tatsache,das es so "nicht" geht.
wenn ich die union jetz aber in 2 Bytwerte unterteile kann ich sie ja 
nicht mehr als ein ganzes in einer Schleife ansprechen.

By
Wolfgang

von Urks (Gast)


Lesenswert?

>was du da sagst gib ich dir recht, habe ich aber auch schon geschrieben

So? Wo ist der Code?

>ändert aber nichts an der Tatsache,das es so "nicht" geht.
Worin äussert sich das?

>wenn ich die union jetz aber in 2 Bytwerte unterteile kann ich sie ja
>nicht mehr als ein ganzes in einer Schleife ansprechen.

Ich zitiere mich mal selbst:

>Das Problem ist erstmal nicht ob ein oder zwei Bytes. Das Problem ist,
>das der Compiler nicht weiss, welches der union Mitglieder er nun
>behandeln soll. Das eine, das Du mit "byte" benannt hast, ist es wohl
>nicht. Aber, nur mal angenommen, Du wolltest (<ironie> das ist natürlich
>völlig abwegig </ironie>) die struct irgendwie am Schlafittchen packen,
>sie wollte von Dir, das Du ihren Namen nennst, sonst will Sie Dein Kind,
>wie würdest Du sie wohl nennen?

von Wolfgang H. (hastekene)


Lesenswert?

Bringt wohl so nichts
hab´s mittlerweile anders gelöst

uint8_t    ledswitch[14];

#define    aktiv  1

#define    ein  2


by
Wolfgang

von Urks (Gast)


Lesenswert?

>wenn ich die union jetz aber in 2 Bytwerte unterteile kann ich sie ja
>nicht mehr als ein ganzes in einer Schleife ansprechen.

Du willst hier mehrere Probleme auf einmal lösen, denke ich. Das ist 
ganz sinnlos.

1. Überleg Dir was Du erreichen willst.
2. Überleg Dir wie Du es erreichen willst.

Der Witz bei der union ist ja gerade das ich hier mehrere Typen haben 
kann die sich im Speicher überdecken.

union {
  struct bytewise {
    byte a;
    byte b;
  } ab;
  int c;
  float d;
  double k;
};

Mit Schleife oder Krawatte hat das nichts zu tun.

Nur, Du musst die Dinger irgendwie benennen. Oben hat ist Dein 
union-Mitglied nicht benannt. Nur ein anynymes Ding.

von Urks (Gast)


Lesenswert?

>Bringt wohl so nichts

Ja. So fertige Tütenlösungen für Copy'nPaste sind nicht meine Sache. Ich 
helfe unter der Voraussetzung das der Beratene liest und mitdenkt.

von gast (Gast)


Lesenswert?

union
{
int byte;
struct
{
  unsigned Leds1:1;
  unsigned Leds2:1;
  unsigned Leds3:1;
  unsigned Leds4:1;
  unsigned Leds5:1;
  unsigned Leds6:1;
  unsigned Leds7:1;
  unsigned Leds8:1;
  unsigned Leds9:1;
  unsigned Leds10:1;
  unsigned Leds11:1;
  unsigned Leds12:1;
  unsigned Leds13:1;
  unsigned Leds14:1;

};
}volatile ledset;



wenn ich jetzt mit

ledset |=(1<<1);




was mich da wundert
meckert der compiler nicht ?
wegen unsigned Ledsxxx?  da fehlt iwie ein datentyp

dann würde es glaube gehen wenn man den member der union anspricht

also ledset.byte |= (1<<1);
oder ledset.lLeds1

von Wolfgang H. (hastekene)


Lesenswert?

Urks schrieb:
>>Bringt wohl so nichts
>
> Ja. So fertige Tütenlösungen für Copy'nPaste sind nicht meine Sache. Ich
> helfe unter der Voraussetzung das der Beratene liest und mitdenkt.

verlangt ja auch keiner von dir .
ich bin ja froh über jede Antwort.

Es ist ja nicht so das ich hier gleich meine Frage stelle ohne mich 
vorher anderweitig zu informieren.

Eine Antwort zeigt einen schließlich wenn mann in die falsche Richtung 
denkt.

 C ist halt nicht Assembler und schon gar nicht Delphi.

Aufgrund vorheriger Antworten stellt sich mir schon wieder eine neue 
Frage.

Was bedeutet dieses:

union {
  struct bytewise {
    byte a;
    byte b;
  } ab;
  int c;
  float d;
  double k;
};

wie spreche ich jetzt byte a an ?


By
Wolfgang

von Stefan E. (sternst)


Lesenswert?

Wolfgang Hopperdietzel schrieb:
> wie spreche ich jetzt byte a an ?
1
XXX.ab.a = 42;

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Schreib das "byte" (das ein Word ist) hinter die anonyme Struktur!

Johann

von Stefan E. (sternst)


Lesenswert?

Johann L. schrieb:
> Schreib das "byte" (das ein Word ist) hinter die anonyme Struktur!

???

Das "byte" ist doch hier anscheinend ein eigener 8-Bit Typ.
Schon klar, dass er vergessen hat, hier überhaupt eine konkrete Variable 
zu definieren. Daher das "XXX" in meinem Post.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> Johann L. schrieb:
>> Schreib das "byte" (das ein Word ist) hinter die anonyme Struktur!
>
> ???
>
> Das "byte" ist doch hier anscheinend ein eigener 8-Bit Typ.
1
typedef union
2
{
3
    struct
4
    {
5
        unsigned Led1:1;
6
        unsigned Led2:1;
7
        unsigned Led3:1;
8
        unsigned Led4:1;
9
        unsigned Led5:1;
10
        unsigned Led6:1;
11
        unsigned Led7:1;
12
        unsigned Led8:1;
13
        unsigned Led9:1;
14
        unsigned Led10:1;
15
        unsigned Led11:1;
16
        unsigned Led12:1;
17
        unsigned Led13:1;
18
        unsigned Led14:1;
19
        unsigned Led15:1;
20
        unsigned Led16:1;
21
    };
22
    
23
    int byte;
24
} ledset_t;
25
26
volatile ledset_t ledset;
27
28
void foo (ledset_t leds)
29
{
30
    leds.Led12 = 0;
31
    leds.byte = 0xff;
32
}

Johann

von Stefan E. (sternst)


Lesenswert?

Ach so, das war auf die ursprüngliche Frage bezogen, nicht auf die neue 
(wie meins). ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> Ach so, das war auf die ursprüngliche Frage bezogen, nicht auf die neue
> (wie meins). ;-)

Jepp. Zu Beachten auf AVR ist allerdings Compilerfehler: avr-gcc

von Karl H. (kbuchegg)


Lesenswert?

Woher kommt eigentlich dieser Unsinn, erst mal grundsätzlich mit 
anonymen Strukturen und Unions um sich zu schmeissen?

Jeder meint immer, er muss so seinen Quellcode so kompakt wie nur 
irgendwie möglich schreiben um dann irgendwann festzustellen, dass man 
sich damit eigentlich meistens ins eigene Knie schiesst.

Gebt doch den eigenen Datentypen Namen!
(Und kauft euch ein C-Buch um zu lernen was denn der ganze 
Buchstabenhaufen eigentlich bedeutet)

von Rolf Magnus (Gast)


Lesenswert?

> Der Witz bei der union ist ja gerade das ich hier mehrere Typen haben
> kann die sich im Speicher überdecken.

Daß sie sich im Speicher überdecken, ist eher ein Nebeneffekt. Eine 
union ist im Prinzip eine struct, bei der ich nicht mehrere Member 
gleichzeitig benutzen darf. In C ist es eigentlich verboten, aus einer 
union ein anderes Element zu lesen, als das, das man zuletzt beschrieben 
hat. Eine Konvertierung über den Umweg einer Union ist nicht vorgesehen 
und eigentlich ein Fehler. Dafür sind Casts gedacht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
>> Der Witz bei der union ist ja gerade das ich hier mehrere Typen haben
>> kann die sich im Speicher überdecken.
>
> Daß sie sich im Speicher überdecken, ist eher ein Nebeneffekt. Eine
> union ist im Prinzip eine struct, bei der ich nicht mehrere Member
> gleichzeitig benutzen darf. In C ist es eigentlich verboten, aus einer
> union ein anderes Element zu lesen, als das, das man zuletzt beschrieben
> hat. Eine Konvertierung über den Umweg einer Union ist nicht vorgesehen
> und eigentlich ein Fehler. Dafür sind Casts gedacht.

Ein Cast ist eine Typumwandlung, eine Union ist eine andere Sicht auf 
die Daten. Das ist was komplett anderes.

Es ist zB nicht möglich, eine Struktur auf eine andere zu Casten. Ebenso 
liefert  ein
1
    float f;
2
    int i = (int) float;
was komplett anderes ab als eine Union einmal als .asInt und einmal als 
.asFloat auszulesen, womit man auf die Binärdarstellun eines float 
zugreifen kann und wie es bei Soft-Float Implementierungen auch gemacht 
wird und korrekt ist. Der Cast beinhaltet hingegen nen ganzen Batzen 
Arithmetik.

Johann

von Rolf Magnus (Gast)


Lesenswert?

> Ein Cast ist eine Typumwandlung, eine Union ist eine andere Sicht auf
> die Daten. Das ist was komplett anderes.

Dafür ist eine Union gar nicht gedacht. Eine andere Sicht bekommst du, 
indem du die Adresse einer Variablen nimmst und dann in einen Pointer 
auf den gewünschten Zieltyp castest.

> Es ist zB nicht möglich, eine Struktur auf eine andere zu Casten.

Es ist aber möglich, einen Zeiger darauf zu Casten und dann zu 
dereferenzieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
>> Ein Cast ist eine Typumwandlung, eine Union ist eine andere Sicht auf
>> die Daten. Das ist was komplett anderes.
>
> Dafür ist eine Union gar nicht gedacht. Eine andere Sicht bekommst du,
> indem du die Adresse einer Variablen nimmst und dann in einen Pointer
> auf den gewünschten Zieltyp castest.
>
>> Es ist zB nicht möglich, eine Struktur auf eine andere zu Casten.
>
> Es ist aber möglich, einen Zeiger darauf zu Casten und dann zu
> dereferenzieren.

Das birgt Fehler durch Strikt-Aliasing.

Von Dinge, die je nachdem, wie weit ein C-Compiler gegen die 
C-Spezifikation optimiert, abschmieren oder nicht, sollte man die Finger 
lassen.

Früher oder später wird dann wieder rumgeheult "Compilerfehler: GCC 
macht falschen Code bei Optimierung".

Johann

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Und bevor Fragen kommen, darf ich aus dem GCC-Handbuch zitieren:

-fstrict-aliasing

Allows the compiler to assume the strictest aliasing rules applicable to 
the language being compiled. For C (and C++), this activates 
optimizations based on the type of expressions. In particular, an object 
of one type is assumed never to reside at the same address as an object 
of a different type, unless the types are almost the same. For example, 
an unsigned int can alias an int, but not a void* or a double. A 
character type may alias any other type.

Pay special attention to code like this:
1
union a_union {
2
  int i;
3
  double d;
4
};
5
              
6
int f() {
7
  a_union t;
8
  t.d = 3.0;
9
  return t.i;
10
}

The practice of reading from a different union member than the one most 
recently written to (called “type-punning”) is common. Even with 
-fstrict-aliasing, type-punning is allowed, provided the memory is 
accessed through the union type. So, the code above will work as 
expected. See Structures unions enumerations and bit-fields 
implementation. However, this code might not:
1
int f() {
2
  a_union t;
3
  int* ip;
4
  t.d = 3.0;
5
  ip = &t.i;
6
  return *ip;
7
}
Similarly, access by taking the address, casting the resulting pointer 
and dereferencing the result has undefined behavior, even if the cast 
uses a union type, e.g.:
1
int f() {
2
  double d = 3.0;
3
  return ((union a_union *) &d)->i;
4
}

The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os.

Johann

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.