www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit struct und union


Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Wäre cool wenn mir jemand sagen könnte, was an diesem Code hier nicht 
korrekt ist:
typedef union {
   unsigned short u16;
   struct {
      unsigned char lowbyte : 8;
      unsigned char highbyte : 8;
   } byte;
   struct {
      unsigned char b0 : 1;
      unsigned char b1 : 1;
      unsigned char b2 : 1;
      unsigned char b3 : 1;
      unsigned char b4 : 1;
      unsigned char b5 : 1;
      unsigned char b6 : 1;
      unsigned char b7 : 1;
   } bit;
} FontType;

struct {
   FontType Header;
   unsigned short *Data;
   unsigned char Width;
   unsigned char Height;
   unsigned char Style;
   unsigned char LetterSpacing;
   unsigned char NumberOfChars = Header.byte.highbyte;
   unsigned char IsFixed = Header.bit.b0;
   unsigned char IsVariable = Header.bit.b1;
   unsigned char IsScanX = Header.bit.b6;
   unsigned char IsScanY = Header.bit.b7;
   unsigned char IsExtendedHeader = Header.bit.b3;
} TFont;

Es geht darum, Code von Basic nach C zu übersetzen, wobei der 
Basic-Compiler schon Funktionen zum Zugriff auf High-/Lowbyte und 
einzelne Bits eingebaut hat. TFont existierte entsprechend schon, so 
dass ich mir etwas einfallen lassen muss, um das so ähnlich wie möglich 
in C beibehalten zu können.

Jedenfalls wirft der Compiler im TFont-Struct auf den Zeilen, wo ich die 
FontType-Variable Header verwende, einen Fehler dieser Art:

../Graphics.c:186: error: expected ':', ',', ';', '}' or '__attribute__' 
before '=' token

Vielen Dank.

Grüsse
Martin

P.S.: Eine weitere Frage brennt mir auch schon unter den Nägeln: Wenn 
das Problem oben gelöst ist, wie greife ich dann auf die 
Pointer-Variable zu? *Font.Data?

Autor: Gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

ich hab die obige Definition mal im Borland C++ Builder eingefügt. Der 
Borland meckert das hier an:

   unsigned char NumberOfChars = Header.byte.highbyte;
   unsigned char IsFixed = Header.bit.b0;
   unsigned char IsVariable = Header.bit.b1;
   unsigned char IsScanX = Header.bit.b6;
   unsigned char IsScanY = Header.bit.b7;
   unsigned char IsExtendedHeader = Header.bit.b3;

"Zuweisung von Werten während der Definition nicht möglich."

Zugriff würde erfolgen: TFiont.Header.u16 = 0; z.B.
Da es innerhalb vom Borland C++ Builder schon ein "TFont" gibt, ist eine 
Variable oder Definition von TFont ungünstig. Müsste also bei Borland 
idealerweise anders heissen.

Gruß
Gerhard

Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau, AVR-GCC meckert nur bei der ersten der von dir erwähnten 
Zeilen, wenn man die auskommentiert bei der nächsten etc...

Was heisst das jetzt genau? Sorry da komm ich nicht selbst drauf, kann 
ein Spezi mir bitte den entschedenden Hinweis geben, danke.

Gruss
Martin

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin Geissmann schrieb:
> Was heisst das jetzt genau?
Was heisst was?

Beziehst Du Dich auf
> "Zuweisung von Werten während der Definition nicht möglich."
Was verstehst Du daran nicht?

Autor: Star Keeper (starkeeper)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist doch ziemlich einfach, du kannst in einer Typdefinition keine 
Werte zuweisen!
Diese Zeilen sind alle falsch:
   unsigned char NumberOfChars = Header.byte.highbyte;
   unsigned char IsFixed = Header.bit.b0;
   unsigned char IsVariable = Header.bit.b1;
   unsigned char IsScanX = Header.bit.b6;
   unsigned char IsScanY = Header.bit.b7;
   unsigned char IsExtendedHeader = Header.bit.b3;

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was heisst das jetzt genau? Sorry da komm ich nicht selbst drauf, kann
>ein Spezi mir bitte den entschedenden Hinweis geben, danke.

Datt jeht in C und auch in C++, und eigentlich auch sonst grundsätzlich, 
so nicht. Du versuchst, einer Variablen einen Wert aus einer anderen 
Variablen zuzuweisen, obwohl diese andere noch gar nicht initialisiert 
ist.

Das wird so auch in Basic nicht gehen, da wirst du ein paar Zeilen 
Programmcode basteln müssen.

Der C-Compiler meckert allerdings aus einem anderen Grund:

Variablen lassen sich in C während der Deklaration nur mit Konstanten 
initialisieren, und Konstanten meint da wirklich Konstanten im Sinne von 
42.

C++ würde auch constant deklarierte Variablen akzeptieren, aber nichtmal 
so etwas hast du vorliegen.

Oliver

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

Bewertung
0 lesenswert
nicht lesenswert
Ausserdem ist die ganze Vorgehensweise, sofern ich die Absicht dahinter 
richtig interpretiere, mehr als zweifelhaft (auch wenn das gültiges C 
wäre).

Man speichert nicht dieselbe Information 2 mal in einer Datenstruktur! 
Niemals.

Erstens ist es Platzverschwendung
Zweitens hat man immer das Problem, dass die beiden Informationsträger 
auseinanderlaufen können und dann stellt sich die Frage: Welche gilt 
denn jetzt?

Schmeiss die Member NumberOfChars, IsFixed, IsVariable, IsScanX, IsScanY 
und IsExtendedHeader aus der struct raus und ersetze sie durch 
Zugriffsfunktionen, die sich die relevanten Werte direkt aus Header 
holen bzw. dort ablegen.

Autor: Heinz Heizer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist doch ein Union, da greift er doch auf den gleichen 
Speicherbereich zu, oder nicht?

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

Bewertung
0 lesenswert
nicht lesenswert
Heinz Heizer schrieb:
> Das ist doch ein Union, da greift er doch auf den gleichen
> Speicherbereich zu, oder nicht?

Nö.

Die Idee, so wie ich das aus dem Code rauslese, ist es einen Member 
Header zu haben, in dem alles drinnen ist.

struct {
   FontType Header;


Und irgendwie magisch sollen sich die Member

   unsigned char NumberOfChars = Header.byte.highbyte;
   unsigned char IsFixed = Header.bit.b0;
   unsigned char IsVariable = Header.bit.b1;
   unsigned char IsScanX = Header.bit.b6;
   unsigned char IsScanY = Header.bit.b7;
   unsigned char IsExtendedHeader = Header.bit.b3;

magisch an diesem Header bedienen und einzelne Informationen daraus in 
neuen Members magisch zur Verfügung stellen.

Das hat erst mal nichts mit der Union an sich zu tun

struct {
  int i;
  int j = i;
}

wäre eine kürzere Version mit genau der gleichen Grundidee.
Das das so in C nichts wird, dürfte klar sein. Da wird wohl in BASCOM 
ein Alias gestanden haben. Den muss man aber in C anders implementieren.

Autor: Andreas Kanzler (scavanger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, aber warum macht ersich erst eine union, nur um sie dann gleich 
wieder in einer structure  zu verwenden? Das ist das doppelte was Kar 
heinz meint.

Ausserdem, wenn man schon eine Struktur will und sie gleich 
initialisieren will dann bitte so:
struct Struktur{
      int foo;
      char name[10];  
} myStruct = {42, "Wilma"};

Autor: Eddy Current (chrisi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ja, aber warum macht ersich erst eine union, nur um sie dann gleich
>wieder in einer structure  zu verwenden? Das ist das doppelte was Kar
>heinz meint.

Weil das mit dem union noch nicht richtig angekommen ist.

Ein Auszug aus dem Original Basic-Source wäre angenehm. Letztlich läuft 
es auf sowas hinaus:

struct {
   unsigned char Width;
   unsigned char Height;
   unsigned char Style;
   unsigned char LetterSpacing;
   unsigned char NumberOfChars;

   // Alles in einem Byte
   unsigned char IsScanY : 1;
   unsigned char IsScanX : 1;
   unsigned char Unused : 3;
   unsigned char IsExtendedHeader : 1;
   unsigned char IsVariable : 1;
   unsigned char IsFixed : 1;
} THeader;

struct {
   struct THeader Header;
   unsigned short *Data;
} TFont;

Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich poste euch hier wie gewünscht mal noch den original Basic-Code 
(nicht Bascom):
Public Structure TFont
   Header As Word
   Data As Word
   Width As Byte
   Height As Byte
   Style As Byte
   LetterSpacing As Byte
   NumberOfChars As Header.Byte1
   IsFixed As Header.Booleans(0)
   IsVariable As Header.Booleans(1)
   IsScanX As Header.Booleans(6)
   IsScanY As Header.Booleans(7)
   IsExtendedHeader As Header.Booleans(3)
End Structure

Die Byte1 und Booleans-Makros stehen hier offenbar schon zur Verfügung.

Wie gesagt, es ging mir darum, dass ich in C genau gleich auf die Daten 
zugreifen kann wie im Originalprogramm, egal ob es schönes C ist oder 
nicht. Wahrscheinlich kommen da aber noch viele weitere Probleme hinzu, 
so dass wohl nichts daraus wird.

Gruss
Martin

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, du wirst zunächst mal verstehen müssen, was der Basic-Code da 
wirklich bedeutet. Dann lässt sich sowas auch in C nachbauen.

Meine Vermutung ist die, daß da tatsächlich eine Art union entsteht, die 
das header-byte zusätzlich in einzelne bits auflöst. Etwa in der Art:
typedef struct {
   uint16_t header;
   uint16_t data;
   uint8_t Width;
   uint8_t Height;
   uint8_t Style;
   uint8_t LetterSpacing;
   uint8_t NumberOfChars;
} TFont;

typedef struct {
   // Alles in einem Byte
   unsigned char IsScanY : 1;
   unsigned char IsScanX : 1;
   unsigned char Unused : 3;
   unsigned char IsExtendedHeader : 1;
   unsigned char IsVariable : 1;
   unsigned char IsFixed : 1;
} Booleans ;

typedef union {
   TFont myFont;
   Booleans myBooleans;
} myUnion;

Oliver

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.