www.mikrocontroller.net

Forum: Compiler & IDEs union-Frage


Autor: beta-frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallöchen,

eine union kann man ja gut benutzen für so etwas in der Art:

typedef struct{
  U8 x; //Koordinate
  U8 y; //Koordinate
}point_t;

typedef union{
  U16 alle;
  point_t einzeln;
}xy_u;

xy_u xy;
xy.einzeln.x = 3;
xy.einzeln.y = 4;
mach_irgendwas(xy);
xy.alle = 0;  //Alle auf einen Streich gelöscht

Aber wie stelle ich das beispielhaft für nachfolgendes an?

typedef struct{
  U8 x; //Koordinate
  U8 y; //Koordinate
  U8 z; //Koordinate
}point_t;

typedef union{
  U24 alle; //3-byte gibts aber nicht...!
  point_t einzeln;
}xyz_u;

Da die union wiederum in einer längeren Tabelle verwendet wird, möchte
ich nicht z.B. U32 verbraten, wenn theoretische U24 reichen würde.

typedef struct{
   xyz_u   xyz;
   U8      foo;
}table_t;

table_t table[] = {/* viele Einträge*/};

Autor: Wolfgang Horn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, Frank-in-der-Beta-Version :-)

was sagt Dein Assembler-Listing? Legt der Compiler structs mit 1* u16
und 1* u8-Variablen lückenlos an, oder läßt er sowieso eine Lücke?
Ist das progmem-Konstanten genauso wie bei RAM und EEPROM?

Falls er structs mit einer ungeradzahligen Anzahl u8 lückenlos packt,
wüßte ich keine bessere Lösung als die Tabelle als point_t liste[] zu
speichern und die union xy_u nur innerhalb einer Funktion zu
deklarieren.

Ciao
Wolfgang Horn

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi beta-frank

> eine union kann man ja gut benutzen für so etwas in der Art:

Mach das nicht.
In diesem Fall kannst du wie folgt vorgehen:

point_t xy;

xy.x = 0;
xy.y = 0;

oder meinetwegen

xy.x = xy.y = 0;

aber geh nicht den Weg über eine union. Würde mich sehr wundern
wenn das langsamer oder schneller wäre als die Zuweisung über
die union.
Selbst die Verwendung einer union um einen bestimmten Datentyp in
Bytes aufzudröseln ist genau genommen vom C-Sprachstandard nicht
gedeckt. Deine Variante ist weit davon entfernt auch nur ansatzweise
legal zu sein.

Wenn du unbedingt eine Struktur in einem Rutsch auf
alle Bytes 0 setzen willst, dann mach das so:

   memset( &xy, 0, sizeof( xy ) );

das ist legal und funktioniert auch dann, wenn der Compiler
Padding benutzt. Das Monster kannst du, wenn du willst noch
in einem schicken Makro verpacken:

#define CLEAR(x)  memset( &(x), 0, sizeof( x ) )

und damit schreiben:

  point_t xy;
  CLEAR( xy );

Autor: beta-frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Eure Antworten! Wenn ich über das beta-Stadium schon hinaus
wäre, bräuchte ich ja nicht fragen;-))

Ich versuche, nochmal genauer zu erklären was ich erreichen möchte:

Ich bekomme 6 U8 Werte nacheinander, die ich einzeln und nacheinander
ermittle und erstmal in einer Structvariablen ablege/sammle. Es gibt
nur rund 20 verschiedene Kombinationen der 6 Werte, welche ich nun
mittels einer Tabelle ermitteln will (und dann die entsprechene
Callback aus 20 möglichen Callbacks aufrufen kann).

Das ganze darf aber auch nicht allzu viel Rechenzeit benötigen. Mein
nächster Ansatz ist nun (Beispielhaft wieder mit 3 U8-Variablen)
typedef struct{
  U8 x; //Koordinate
  U8 y; //Koordinate
  U8 z; //Koordinate
}point_t;

typedef struct{
   point_t xyz;
   PFKT    pfkt;  //Funktionszeiger auf Callback
}table_t;

table_t table[] = {
  {{1,2,3},callback_1},
  {{7,8,9},callback_2},
};

void main(void){
  point_t live={7,8,9};
  U8 cnt;
  for(cnt=0; cnt<sizeof(table)/sizeof(table_t); ++cnt)
    if( strncmp((char*)&table[cnt], (char*)&live, sizeof(point_t))==0)
      table[cnt].pfkt();//TabellenÜbereinstimmung gefunden
}

Würde mich über einen Kommentar / Verbesserungsvorschlag freuen.

Frank

Autor: beta-frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS:
das sinnvlolle
break; 
, um in der for-Schleife nicht unnötig länger zu weilen liefere ich
hiermit nach;-)

Autor: Karsten Brandt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Frank,

ich wage zu bezweifeln, das Du mit einem String-Vergleich den korrekten
Punkt in Deiner Tabelle findest!

besser?:

typedef struct{
  U8 x; //Koordinate
  U8 y; //Koordinate
  U8 z; //Koordinate
}point_t;
 
typedef struct{
   point_t xyz;
   PFKT    pfkt;  //Funktionszeiger auf Callback
}table_t;
 
table_t table[] = {
  {{1,2,3},callback_1},
  {{7,8,9},callback_2},
};
 
bool equalPoints(point_t p1, point_t p2)
{
  return ( ( p1.x == p2.x ) &&
           ( p1.y == p2.y ) &&
           ( p1.z == p2.z ) );
}

void main(void){
  point_t live={7,8,9};
  U8 cnt;
  for(cnt=0; cnt<sizeof(table)/sizeof(table_t); ++cnt)
    if( equalPoints(table[cnt].xyz, live)
      table[cnt].pfkt();//TabellenÜbereinstimmung gefunden
} 


Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich wage zu bezweifeln, das Du mit einem String-Vergleich den
> korrekten Punkt in Deiner Tabelle findest!

Yep.

@Frank
Die Idee die du hattest, ist doch dass alle Bytes
identisch sein muessen.
Hier reden wir von Bytes, d.h. die str... Funktionen
sind keine gute Wahl. Unter anderem deshalb da bei
Strings es ja einen Bytewert mit einer ganz bestimmten
Bedeutung gibt. Das 0-Byte und es bedeutet  'End of String'.
Alle str... Funktionen wissen das und behandeln das auch
entsprechend.

Wenn du auf Byte-Ebene arbeitest: mem... Funktionen
Wenn die Bytes zusätzlich noch die Vorausssetzungen für
einen String erfüllen: str... Funktionen

Oder aber das ganze klassisch ausprogrammieren, so wie Karsten
das vorschlägt.

Autor: beta-frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Variante
bool equalPoints(point_t p1, point_t p2)
{
  return ( ( p1.x == p2.x ) &&
           ( p1.y == p2.y ) &&
           ( p1.z == p2.z ) );
}
werde ich verwenden. Ich dachte, strncmp(..) (ausgesprochen vermutlich
String_N_Compare) vergleicht stur N zeichen ohne auf '\0' zu achten.
Achtet sie aber...

Vielen Dank für Eure Unterstützung!

Frank

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich dachte, strncmp(..) (ausgesprochen vermutlich
> String_N_Compare) vergleicht stur N zeichen ohne auf '\0' zu
achten.

strncmp benutzt man gerne zum Parsen wenn man eine Eingabezeile
hat und zb. weiss dass die mit einem bestimmten Schlüsselwort
anfangen muss.
zb. Hast du ein Protokoll
POINT 2, 20, 30, 40
LINE 5, 6

Um jetzt festzustellen ob das eine POINT oder eine LINE
Zeile ist, kannst du machen:

   if( strncmp( Input, "POINT", 5 ) == 0 )
     // war ein POINT

   else if( strncmp( Input, "LINE", 4 ) == 0 )
     // war ein LINE

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.