Forum: Compiler & IDEs Agregat in C


von Zauberlehrling (Gast)


Lesenswert?

Aus VHDL kenne ich sogenannte Aggregate.
Habe mal ein Beispiel gemacht:
1
Mein_Aggregat <= (10,Bla7,Bla5,Bla3,Bla1,10);


In C habe ich Bitfelder in einer struct,
hier ein Beispiel:
1
struct {
2
   unsigned Bla0:1;
3
   unsigned Bla1:1;
4
   unsigned Bla2:1;
5
   unsigned Bla3:1;
6
   unsigned Bla4:1;
7
   unsigned Bla5:1;
8
   unsigned Bla6:1;
9
   unsigned Bla7:1;
10
} Mein_Status;

Wie kann ich in C Statusbits aus verschiedenen Struct's zusammenfassen 
wie in VHDL in einem Aggregat?

von Karl H. (kbuchegg)


Lesenswert?

Zauberlehrling schrieb:

> Wie kann ich in C Statusbits aus verschiedenen Struct's zusammenfassen

Du meinst automatisch?

Gar nicht.

> wie in VHDL in einem Aggregat?

Ich glaube nicht, dass sich die beiden Konzepte entsprechen.

von Zappelphilipp (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ich glaube nicht, dass sich die beiden Konzepte entsprechen.
>

Mir ist schon klar, das es so einfach nicht geht.
Ich kann es natürlich mit viel maskieren und schieben hinkriegen, hier 
einmal ein Beispiel:
1
Mein_Send_Byte = 0b10000010 
2
                | ((Bla & 0x01) << 5)
3
                | ((Bla & 0x04) >> 2)
4
                | ((Bla & 0x10) >> 1)
5
                | ((Bla & 0x40) >> 4);

Nur möchte ich zur besseren Lesbarkeit es so haben wie in VHDL mit dem 
Aggregat.
Kann man den Leuten, die C weiterentwickeln, sowas nicht vorschlagen.
Wie heisst denn dieses Kommitee, das den Standart von C89 und C99 
festgelegt hat.
Gibt es vieleicht bald ein C2011?

von Zappelphilipp (Gast)


Lesenswert?

Auf so Bitfelder greife ich z.B. so zu:
1
if (Mein_Status.Bla3 && Mein_Status.Bla7) mach_was;

Habe ich da noch andere Möglichkeiten?


BTW. bevor noch jemand verwirrt ist: Zauberlehling = Zappelphillip  ;-)

von Karl H. (kbuchegg)


Lesenswert?

Zappelphilipp schrieb:

> Mir ist schon klar, das es so einfach nicht geht.
> Ich kann es natürlich mit viel maskieren und schieben hinkriegen, hier
> einmal ein Beispiel:
>
1
> Mein_Send_Byte = 0b10000010
2
>                 | ((Bla & 0x01) << 5)
3
>                 | ((Bla & 0x04) >> 2)
4
>                 | ((Bla & 0x10) >> 1)
5
>                 | ((Bla & 0x40) >> 4);
6
>
>
> Nur möchte ich zur besseren Lesbarkeit es so haben wie in VHDL mit dem
> Aggregat.

Mach dir eine Funktion, die die Details versteckt und gut ists.
Letzten Endes: Ob du das schieben explizit machst oder ob du es dem 
Compiler aufzwingst, ist für den Prozessor gehupft wie gesprungen.

Du kannst natürlich machen:
1
  Mein_Status alt1, alt2;   // von diesen beiden einige Bits ...
2
  Mein_Status neu;          // ... hierher zusammenkopieren
3
4
  neu.Bla1 = alt_1.Bla5;
5
  neu.Bla2 = alt_1.Bla7;
6
  neu.Bla3 = alt_2.Bla4;
7
8
  etc.

aber letzten Endes mündet auch das in Verschieben und Verodern :-)

> Kann man den Leuten, die C weiterentwickeln, sowas nicht vorschlagen.

Kann man.
Aber wozu? Das was du willst kannst du erreichen. 
Sprachweiterentwicklungen nur damit du dir 3 Zeilen Tipparbeit sparst, 
die ausser dir niemand braucht, da wird sich kaum eine Mehrheit dafür 
finden :-)

von Zappelphilipp (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sprachweiterentwicklungen nur damit du dir 3 Zeilen Tipparbeit sparst,

Naja, der Wunsch, ein paar Zeilen Tipparbeit zu sparen (und natürlich 
Portierbarkeit) waren afaik die Hauptantriebsfedern, überhaupt 
Hochsprachen zu entwickeln  ;-)

von Karl H. (kbuchegg)


Lesenswert?

Zappelphilipp schrieb:
> Karl heinz Buchegger schrieb:
>> Sprachweiterentwicklungen nur damit du dir 3 Zeilen Tipparbeit sparst,
>
> Naja, der Wunsch, ein paar Zeilen Tipparbeit zu sparen (und natürlich
> Portierbarkeit) waren afaik die Hauptantriebsfedern, überhaupt
> Hochsprachen zu entwickeln  ;-)

OK. Mach einen Vorschlag.
Wie sollte eine derartige Erweiterung deiner Meinung nach aussehen?

Aber diesmal bitte ganz konkret.
Wie soll die C-Syntax aussehen? Welche Aktion soll erfolgen? Am besten 
demonstriertst du das alles in einem hypotetischen Programm, welches 
dein neues Sprachfeature nutzt.

Und ach ja: neue Schlüsselwörter sind im C-Kommitee gar nicht gerne 
gesehen. Wenn geht, benutz vorhandene Schlüsselwörter.

Ich spiel Normungsgremium und seh mir den Vorschlag an.
Bedenke aber, dass du mit Aussagen wie in deinem Eröffnungsposting (wie 
in VHDL) nicht durchkommen wirst. Das musst du mir schon konkreter 
verkaufen.

von Zappelphilipp (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ich spiel Normungsgremium und seh mir den Vorschlag an.

Meine Freundin hat eben angerufen, will mit mir baden gehen...
deshalb schlunze ich das mal eben so aif die Schnelle zusammen:

Ein Programmfragment könnte z.B. so aussehen:
1
struct {
2
   unsigned Bla0:1;
3
   unsigned Bla1:1;
4
   unsigned Bla2:1;
5
   unsigned Bla3:1;
6
   unsigned Bla4:1;
7
   unsigned Bla5:1;
8
   unsigned Bla6:1;
9
   unsigned Bla7:1;
10
} Mein_Status;
11
12
struct {
13
   unsigned Bla0:1;
14
   unsigned Bla1:1;
15
   unsigned Bla2:1;
16
   unsigned Bla3:1;
17
   unsigned Bla4:1;
18
   unsigned Bla5:1;
19
   unsigned Bla6:1;
20
   unsigned Bla7:1;
21
} Dein_Status;
22
23
Mein_Aggregat = {['1','0',Mein_Status.Bla7,
24
                          Dein_Status.Bla5,
25
                          Mein_Status.Bla7,
26
                          Dein_Status.Bla5,
27
                          '1','0']};
28
29
RF_put_char(Mein_Aggregat);

Ich bin dann mal weg ;-)

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


Lesenswert?

> Mein_Aggregat =

Mein_Aggregat ist ja nicht einmal definiert worden.

Ein wenig C-Syntax solltest du schon beherrschen, bevor du hier einen
Vorschlag zur Änderung des Standards bringst...  Nein, das schreibt
man nicht mal in 5 Minuten vor dem Badengehen.

"aggregate type" ist im Sinne des C-Standards übrigens ein Überbegriff
für struct/union + arrays.

von faustian (Gast)


Lesenswert?

Haelt ihn doch keiner von ab mit einem struct voller vorinitialisierter 
Zeiger zu arbeiten...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn ich den Zauberlehrling richtig verstanden habe, kommt seinem Wunsch
Folgendes wahrscheinlich am nächsten:
1
struct status {
2
  unsigned int b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
3
};
4
5
int main(void) {
6
  struct status st1 = { 1, 1, 0, 1, 0, 0, 1, 1 }, st2;
7
8
  st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 };
9
  return 0;
10
}

Das Ganze ist C99-konform und funktioniert natürlich auch über mehrere
unterschiedliche Strukturen hinweg.

von Klaus F. (kfalser)


Lesenswert?

Yalu X. schrieb:
> Wenn ich den Zauberlehrling richtig verstanden habe, kommt seinem Wunsch
> Folgendes wahrscheinlich am nächsten:
>
>
1
> struct status {
2
>   unsigned int b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
3
> };
4
> 
5
> int main(void) {
6
>   struct status st1 = { 1, 1, 0, 1, 0, 0, 1, 1 }, st2;
7
> 
8
>   st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 };
9
>   return 0;
10
> }
11
>
>
> Das Ganze ist C99-konform und funktioniert natürlich auch über mehrere
> unterschiedliche Strukturen hinweg.

Nein, das ist wahrscheinlich nicht, das was der Zauberlehrling meint, 
weil st2 hier nur mit den Werten von st1 initialisiert wird.
Wenn sich st1 ändert, zieht st2 nicht mit.

Bei einem Aggregat in VHDL werden mehrere Objekte zusammengefasst und 
unter einem neuen Namen angesprochen.

So etwas ähnliches wurde meiner Erinnerung nach von Anfängern schon 
mehrmals gewünscht, die gerne verschiedene bestehende Variablen zu einer 
Struct zusammenfassen würden.

von Peter D. (peda)


Lesenswert?

Ich vermute mal, daß es sowas nicht gibt, weil das programmtechnisch ein 
höllisch riesiger Aufwand ist.

Wilst Du 8 Bits aus 8 Variablen lesen und zusammenfassen, sind das 
locker 32 Befehle (je Bit: Variable lesen, Bit maskieren, Bit an die 
Stelle schieben, mit Ergebnis verodern).
Deine CPU wird also zur Schnecke gemacht.

Bei nem FPGA sind das dagegen nur programmierte Verbindungen und das 
Zeitverhalten wird nicht verschlechtert.


Peter

von Yalu X. (yalu) (Moderator)


Lesenswert?

Klaus Falser schrieb:
> Nein, das ist wahrscheinlich nicht, das was der Zauberlehrling meint,
> weil st2 hier nur mit den Werten von st1 initialisiert wird.
> Wenn sich st1 ändert, zieht st2 nicht mit.

Ok, dann eben mit einem Makro ;-)
1
#include <stdio.h>
2
3
struct status {
4
  unsigned int b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
5
};
6
7
int main(void) {
8
  struct status st1 = { 1, 1, 0, 1, 0, 0, 1, 1 };
9
  #define st2 (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 }
10
11
  printf("%d\n", st2.b2); // Ausgabe von st2.b2 -> 1
12
  st1.b7 = 0;             // Ändern von st1
13
  printf("%d\n", st2.b2); // Ausgabe von st2.b2 -> 0
14
  return 0;
15
}

Allerdings ist diese Methode ziemlicher Pfusch, weil der Scope von st2
nun nicht mehr lokal ist. Soll st2 hingegen global sein, wär's
vielleicht halbwegs akzeptabel.

Nach wie vor arbeitet die Methode auch nicht bidirektional, d.h. eine
Änderung von st2 wirkt sich nicht auf st1 aus, was aber vielleicht
gewünscht wäre.

In C++ hätte man mit der Überladung von Operatoren etwas bessere
Möglichkeiten, so etwas zu realisieren.

von Klaus (Gast)


Lesenswert?

Vielleicht sollte man auch einfach mal von der VHDL-Denkweise runter 
kommen, dass eine Zuweisung (oder in diesem Fall eine Zusammenfassung) 
von Variablen dauerhaft (also nebenläufig) wirkt, sondern in C einfach 
nur einmal ausgeführt wird. So wie man in VHDL Signale mit 
unterschiedlichen Namen einfach verbinden kann, kann man in C nunmal 
keine Variablen verbinden.

von faustian (Gast)


Lesenswert?

"kann man in C nunmal keine Variablen verbinden."

Ausser man richtet zwei Zeiger auf die selbe Addresse - mit Bitfields 
geht das aber nicht (weil die hardwaremaessig keine echte Addresse 
haben, ausser ggf auf dem 8051).

von Zauberlehrling (Gast)


Lesenswert?

Klaus schrieb:
> Vielleicht sollte man auch einfach mal von der VHDL-Denkweise runter
> kommen, dass eine Zuweisung (oder in diesem Fall eine Zusammenfassung)
> von Variablen dauerhaft (also nebenläufig) wirkt, sondern in C einfach
> nur einmal ausgeführt wird. So wie man in VHDL Signale mit
> unterschiedlichen Namen einfach verbinden kann, kann man in C nunmal
> keine Variablen verbinden.

Sorry, ich habe es leider nicht geschaft genau zu erklären was ich will.
Neuer Versuch:
Ich will Statusbits die in verschiedenen Struct's vorhanden sind in 
einem Char oder short int zusammenfassen und dann per RS232 oder 
RF-Modul usw. verschicken. Die Aktualisierung brauch natürlich nur kurz 
vor dem verschicken passieren, und nicht wie bei VHDL dauernd.

von Updater (Gast)


Lesenswert?

Zauberlehrling schrieb:
> Die Aktualisierung brauch natürlich nur kurz
> vor dem verschicken passieren

Dann ruf kurz vor dem Verschicken die Funktion update() auf ;-)

von Zauberlehrling (Gast)


Lesenswert?

Updater schrieb:
> Dann ruf kurz vor dem Verschicken die Funktion update() auf ;-)

Aber das soll nicht so aussehen:
1
Send_Byte(  0b10000010 
2
         | ((Bla & 0x01) << 5)
3
         | ((Bla & 0x04) >> 2)
4
         | ((Bla & 0x10) >> 1)
5
         | ((Bla & 0x40) >> 4));

sondern z.B. so:
1
Send_Byte = {['1','0',St1.B7,St1.B5,St2.B7,St2.B5,'1','0']};

Es soll nur einfach die ganze Maskiererei und Schieberei verborgen 
werden.
Deshalb habe ich gedacht, wenn das nicht geht, dann sollte C2012 diese 
Möglichkeit enthalten.

von Klaus F. (kfalser)


Lesenswert?

Zauberlehrling schrieb:
> Deshalb habe ich gedacht, wenn das nicht geht, dann sollte C2012 diese
> Möglichkeit enthalten.

Bitte dann gleich die Möglichkeit zum Gelddrucken, Ferrari fahren, 
Gedankenlesen usw. auch mit einbauen....
Wird dann halt ein Major release :-)

von Frederik K. (n0ll4k)


Lesenswert?

Kann man statt dem Ferrari auch ne Porsche nehmen?

Also dafür das es nur verborgen werden soll ist der Aufwand schon recht 
hoch, ich kann zwar jetzt kein VHDL. Aber ich denke wenn man ne neue 
Programmiersprache lernt sollte man halt auch versuchen mit dem Syntax 
und den gegebenen Möglichkeiten klar zu kommen...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Zauberlehrling schrieb:
> Die Aktualisierung brauch natürlich nur kurz vor dem verschicken
> passieren, und nicht wie bei VHDL dauernd.

Zauberlehrling schrieb:
> Aber das soll nicht so aussehen:Send_Byte(  0b10000010
>          | ((Bla & 0x01) << 5)
>          | ((Bla & 0x04) >> 2)
>          | ((Bla & 0x10) >> 1)
>          | ((Bla & 0x40) >> 4));
>
> sondern z.B. so:Send_Byte = {['1','0',St1.B7,St1.B5,St2.B7,St2.B5,'1','0']};
>
> Es soll nur einfach die ganze Maskiererei und Schieberei verborgen
> werden.

Dann war doch das, was ich oben geschrieben habe, gar nicht so daneben:

Yalu X. schrieb:
>   st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 };

Bis auf die zusätzliche Typbezeichnung und den fehlenden eckigen
Klammern ist das sogar die gleiche Syntax. Und darauf musst du nicht
einmal bis 2012 oder noch länger warten, das gibt es schon seit 1999.

von Zauberlehrling (Gast)


Lesenswert?

Yalu X. schrieb:
> Bis auf die zusätzliche Typbezeichnung und den fehlenden eckigen
> Klammern ist das sogar die gleiche Syntax. Und darauf musst du nicht
> einmal bis 2012 oder noch länger warten, das gibt es schon seit 1999.

@ Yalu:
Danke, du bist ein großer Zauberer, bei dir geh ich gern in die Lehre! 
;-)

von Zauberlehrling (Gast)


Lesenswert?

Wenn ich schreibe:
1
#include <avr/io.h>
2
3
struct status {
4
  unsigned int b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
5
};
6
7
unsigned char Mein_Byte;
8
9
int main(void) {
10
  struct status st1,st2;
11
  
12
  st1.b7 = 1;
13
14
  st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 };
15
16
  Mein_Byte =  st2;
17
  return 0;
18
}

Da bekomme ich leider eine incompatible types in assignment Error.
Was tun?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Fehlermeldung bekommst Du wahrscheinlich hier:

    Mein_Byte =  st2;

von Zauberlehrling (Gast)


Lesenswert?

Rufus t. Firefly schrieb:
> Die Fehlermeldung bekommst Du wahrscheinlich hier:
>
>     Mein_Byte =  st2;


Stimmt.
unsigned char und struct status passen nicht zusammen.

Was kann man da tun?

von Scherzkeks (Gast)


Lesenswert?

sich eine Funktion schreiben?
1
unsigned char convert(struct status x)
2
{
3
    // wandle um
4
}
5
6
Mein_Byte = convert(st2);

von Karl H. (kbuchegg)


Lesenswert?

Zauberlehrling schrieb:
> Rufus t. Firefly schrieb:
>> Die Fehlermeldung bekommst Du wahrscheinlich hier:
>>
>>     Mein_Byte =  st2;
>
>
> Stimmt.
> unsigned char und struct status passen nicht zusammen.
>
> Was kann man da tun?



Ähm.
Casten?

von Zauberlehrling (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ähm.
> Casten?
1
#include <avr/io.h>
2
3
struct status {
4
  unsigned char b0:1;
5
  unsigned char b1:1;
6
  unsigned char b2:1;
7
  unsigned char b3:1;
8
  unsigned char b4:1;
9
  unsigned char b5:1;
10
  unsigned char b6:1;
11
  unsigned char b7:1;
12
};
13
14
unsigned char Mein_Byte;
15
16
int main(void) {
17
  struct status st1,st2;
18
  
19
  st1.b7 = 1;
20
21
  st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b3, st1.b1, 1, 0 };
22
23
  Mein_Byte = (unsigned char)st2;
24
  return 0;
25
}

Leider die Fehlermeldung:
aggregate value used where an integer was expected
in der Zeile Mein_Byte = (unsigned char)st2;

von Andreas F. (aferber)


Lesenswert?

Yalu X. schrieb:
> Dann war doch das, was ich oben geschrieben habe, gar nicht so daneben:
> Yalu X. schrieb:
>>   st2 = (struct status){ 1, 0, st1.b7, st1.b5, st1.b7, st1.b5, 1, 0 };

Nur will er das ja dann an ein anderes System übertragen, und da ist 
nicht garantiert, dass eine identisch deklarierte struct auf der 
anderen Seite wirklich Bit für Bit identisch aufgebaut ist. Will man 
Portabilität der Daten erreichen, dann muss man sich schon von Hand auf 
die Ebene der Bits und Bytes begeben.

Andreas

von Karl H. (kbuchegg)


Lesenswert?

Zauberlehrling schrieb:
> Karl heinz Buchegger schrieb:
>> Ähm.
>> Casten?

> Leider die Fehlermeldung:
> *aggregate value used where an integer was expected*
> in der Zeile Mein_Byte = (unsigned char)st2;

Wo ein Wille, da ein Weg :-)
1
    Mein_Byte = *(unsigned char*)&st2;

Das heißt aber nicht, das ich das für eine gute Idee halte!

von Mark B. (markbrandis)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wo ein Wille, da ein Weg :-)    Mein_Byte = *(unsigned char*)&st2;

You evil caster you! ;-)

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.