mikrocontroller.net

Forum: Compiler & IDEs typedef-Problem in VS6


Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

ich plage mich seit geraumer Zeit mit folgendem Problem herum.

Ich habe in header.h folgende Typendefinition:
// header.h

typedef struct
{
   const unsigned int  a;
   const unsigned int   b;
   const unsigned char* c;
   const unsigned char* d;
   const unsigned char* e;
   const unsigned int*  f;
}STRUKTUR;

In einer weiteren Datei source.cpp definiere ich:
// source.cpp

#include <header.h>

const unsigned char udo[] = {1,2,3};
const unsigned char ingo[] = {1,2,3};
const unsigned char hugo[] = {1,2,3};
const unsigned int lotte[] = {1,2,3};

STRUKTUR xyz = 
{
  1,
  2,
  udo,
  ingo,
  hugo,
  lotte
};

Der Compiler quittiert den Dienst mit:
error C2552: 'xyz' : non-aggregates cannot be initialized with initializer list

Ich nutze Visual Studio 6 (auch C++ Code). Ich kann diese Meldung nicht 
nachvollziehen. Hat jemand einen Tipp?

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

Bewertung
0 lesenswert
nicht lesenswert
Hab ein VC++ 6.0 hier.

Hab dein Beispiel aufgesetzt und compiliert.
Keine Fehlermeldung.
Kannst du bitte ein vollständiges, kompilierbares Beispiel
zusammenstellen und vor dem Posten testen ob es die von dir
beobachtete Fehlermeldung hervorbringt.


#include <header.h>

<> solltest du ausschliesslich für System-header Files
reservieren. Für eigene Headerfiles wird " benutzt.

#include "header.h"

Der Unterschied zwischen <> und "" sind rein die Aufsuchpfade
mit denen der Compiler das Header File sucht. Vielleicht liegt
es ja daran, dass du ein Header File einbindest, dass zufällig
genauso heist wie dein eigenes.

Autor: T. H. (pumpkin) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl, ich habe der Umgebung den Pfad in den Optionen gesetzt. Der
Header heißt selbstverständlich nicht header.h, er hat einen sehr
eindeutigen Namen.

Ich habe es genauso wie beschrieben auch mit dem Keil gemacht, keine
Fehlermeldung wie bei dir. Aber VS6 eiert rum. MSDN kann man vergessen,
kein zutreffender Eintrag.

Im Anhang mal das was bei mir nicht läuft neu zusammengestellt.

Danke für die Mühe.

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

Bewertung
0 lesenswert
nicht lesenswert
RAR ist ganz schlecht.
Kann ich auf der Maschine auf der ich bin nicht öffnen.
Kann auch nichts nachinstallieren, da ich keine Admin Rechte habe.
Einen Entzipper hab ich allerdings.

Autor: T. H. (pumpkin) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Aber gerne.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Da sind sie, die beiden Sourcefiles als ZIP-Archiv.

Das Problem liegt darin, daß die Art der Strukturinitialisierung in C++ 
unzulässig ist. Benennt man das *.cpp-Sourcefile (das übrigens kein 
einziges C++-Element enthält) um in *.c, dann lässt sich die Chose 
anstandslos übersetzen.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sowas dachte ich mir. Das Problem: In meiner Headerdatei sind Elemente 
aus C++ (Bibliotheksdefinitionen). Bevor ich jetzt alles auseinander 
stricke: Gibt es eine Möglichkeit das zu umgehen? Was genau ist 
unzulässig? Ich bin nicht (mehr) besonders bewandert in C++.

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

Bewertung
0 lesenswert
nicht lesenswert
Wobei das interessante darin besteht, dass dieser Fehler
erst dann auftritt, wenn der 3-te Pointer in die Struktur
hineinkommt. Bei nur 2 Pointern in der Struktur ist das
kein Problem.

Ich denke mal, dass ist ein Compilerfehler. Auf Anhieb wuesste
ich nicht, warum das laut C++ Standard illegal sein sollte.

> Gibt es eine Möglichkeit das zu umgehen?

Grade im VC++ ausprobiert.
Du kannst der Struktur einen Konstruktor verpassen und dort
eine Initializer List angeben.
typedef struct lcd_font_
{
   const unsigned int      glyph_width;  /* glyph width in pixels              */
                                      /*     0 for variable width fonts     */
   const unsigned int      glyph_height;   /* glyph height for storage           */
   const unsigned char*      glyph_table;     /* font table start address in memory */
   const unsigned char*     mapping_table;   /* used to find the index of a glyph  */
   const unsigned char*     width_table;     /* width table start adress           */
                                      /*        NULL for fixed width fonts  */
   const unsigned int*       offset_table;   /* ks the offsets of the first byte    */
                                       /*                      of each glyph */
  lcd_font_( unsigned int a, unsigned int b,
             const unsigned char* c, const unsigned char* d,
             const unsigned char* e, const unsigned int* f )
      : glyph_width( a ),
        glyph_height( b ),
        glyph_table( c ),
        mapping_table( d ),
        width_table( e ),
        offset_table( f )
      {
      }

}LCD_FONT;

Die Initialisierung in main verändert sich dann ein bischen:
LCD_FONT Courier_New__8 ( 

   0,                 // glyph_width
   13,                 // glyph_height
   Courier_New__8_char_table,     // ptr to glyph_table
   Courier_New__8_mapping_table,   // ptr to mapping_table
   Courier_New__8_width_table,
   Courier_New__8_offset_table
);

Wenn der Konstruktor kein Problem darstellt (keine Kompatibilität
zu C) dann wäre das eine Lösung. Schlimmstenfalls müsste man den
Konstruktor noch mit einem Makro kapseln, so dass er nur bei C++
aktiv wird.

Jetzt wüsste ich nur noch zu gerne, warum dein Code im
Eröffnungsposting ohne Probleme compilierte :-)

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

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Wobei das interessante darin besteht, dass dieser Fehler
> erst dann auftritt, wenn der 3-te Pointer in die Struktur
> hineinkommt. Bei nur 2 Pointern in der Struktur ist das
> kein Problem.

Das nehme ich zurück.
Obwohl. Ich hatte mit einer Teststruktur den Fall, dass es sich
genauso verhalten hat.

Jetzt hab ich mal probehalber folgendes gemacht:
typedef struct vec_
{
   unsigned int      a;
   unsigned int      b;
} vec;

struct vec_ xy = { 0, 5 };

compiliert.

Umgeändert auf (const eingefügt )
typedef struct vec_
{
   const unsigned int      a;
   const unsigned int      b;
} vec;

struct vec_ xy = { 0, 5 };

compiliert nicht.

Geändert auf
typedef struct vec_
{
   unsigned int      a;
   unsigned int      b;
   const unsigned char*      glyph_table;
} vec;

struct vec_ xy = { 0, 5, Courier_New__8_char_table };

compiliert

Dürfte also was mit dem const bei den unsigned int zu tun haben.
Ein Test:
typedef struct
{
   unsigned int      glyph_width;  /* glyph width in pixels              */
                                      /*     0 for variable width fonts     */
   unsigned int      glyph_height;   /* glyph height for storage           */
   const unsigned char*      glyph_table;     /* font table start address in memory */
   const unsigned char*     mapping_table;   /* used to find the index of a glyph  */
   const unsigned char*     width_table;     /* width table start adress           */
                                      /*        NULL for fixed width fonts  */
   const unsigned int*       offset_table;   /* ks the offsets of the first byte    */
                                       /*                      of each glyph */
}LCD_FONT;

und die Originalversion der Initialisierung: COMPILIERT!

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

Bewertung
0 lesenswert
nicht lesenswert
Wobei ich gestehen muss, dass mit nicht klar ist, was dieses
const aus der Strukturdefinition macht. Warum soll das
dann kein Aggregat mehr sein?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass die Anfrage im GCC-Forum gepostet wurde, nahm ich zum Anlass, den
Inhalt von fehler.zip dem GCC zum Fraß vorzuwerfen:

  g++ -pedantic -Wall -Wextra -c courier_new__8_R0_L0_T0_B1.cpp

Bis auf die Warnung vor dem fehlenden Newline am Dateiende meckert der
Compiler nichts, trotz der auf Maximum eingestellten Penibilität. Also
hat einer der beiden Compiler eine Macke. Ich tippe mal auf den VC ;-)

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

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:
> Dass die Anfrage im GCC-Forum gepostet wurde, nahm ich zum Anlass, den
> Inhalt von fehler.zip dem GCC zum Fraß vorzuwerfen:
>
>   g++ -pedantic -Wall -Wextra -c courier_new__8_R0_L0_T0_B1.cpp
>
> Bis auf die Warnung vor dem fehlenden Newline am Dateiende meckert der
> Compiler nichts, trotz der auf Maximum eingestellten Penibilität. Also
> hat einer der beiden Compiler eine Macke. Ich tippe mal auf den VC ;-)

:-)
Oh. Das ist nichts neues. VC 6.0 hat so einige Macken.
Hat allerdings auch schon einige Jährchen auf dem Buckel.
Der wurde 1998 auf die Menschheit losgelassen.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
typedef struct vec_
{
   unsigned int      a;
   unsigned int      b;
   const unsigned char*      glyph_table;
} vec;

Im Gegensatz zu "const unsigned int" bezieht sich das "const" bei "const 
unsigned char*" auf das, worauf der Zeiger zeigt. Die Variable 
glyph_table kann also veraendert werden, nur *glyph_table nicht. Bei 
"unsigned int a;" kann aber tatsaechlich die Variable a nicht veraendert 
werden.
Deswegen schaetze ich, dass einige C-Tricksereien nicht mehr 
funktionieren, weil das eben kein gewoehnlicher C-POD-Typ mehr ist 
(sieht man zum Beispiel daran, dass Zuweisung nicht mehr funktioniert).

Ich wuerde wahrscheinlich einfach ganz zu C++ wechseln und nicht 
versuchen C/C++ gemischt zu schreiben. Also auch nicht "typedef struct { 
/* ... */ } vec;" nehmen sondern eben direkt "struct vec { ... };". Fuer 
das typedef gibt es in C++ keinen Grund meh. Oder vielleicht noch 
besser, da das Objekt ja offenbar doch ein paar Methoden braucht, gleich 
"class vec { ... };" schreiben.

Autor: T. H. (pumpkin) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal vielen Dank, eure Hilfestellungen sind super!

Aber zu früh gefreut, im Anhang mal das Ganze erweitert um den
scheinbaren Verursacher der Probleme. Ich habe ein wenig rumgespielt und
komme nicht um folgende Fehler herum:

error C2143: Syntaxfehler : Fehlendes ';' vor '*'
error C2501: 'USBDevice' : Fehlende Speicherklasse oder Typbezeichner

Ich habe keine Ahnung in welche Richtung das läuft...

Die Variante mit dem Konstruktor habe ich versucht, leider ohne Erfolg.

Ich möchte das Ganze nicht umstellen auf C++ weil meine Kenntnisse
mittlerweile schlecht sind und das auch zu viel Arbeit nach sich ziehen
würde weil GLCD die Fonts als struct ausspuckt - es soll leicht
handhabbar bleiben.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fehlt wohl einfach nur die Deklaration von CCyUSBDevice ;-)

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht erst CyAPI.h und dann zUSB_API.h includen. Dann müssten 
zumindest die angegeben Fehler weg sein.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:
> Da fehlt wohl einfach nur die Deklaration von CCyUSBDevice ;-)

?

Der Wald, die Bäume, ich.

> Vielleicht erst CyAPI.h und dann zUSB_API.h includen. Dann müssten
> zumindest die angegeben Fehler weg sein.

Tatsächlich. Nur kommen dann weitere 102 Fehler die sich allesamt auf 
die CyAPI.h beziehen.

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

Bewertung
0 lesenswert
nicht lesenswert
T. H. wrote:

> Tatsächlich. Nur kommen dann weitere 102 Fehler die sich allesamt auf
> die CyAPI.h beziehen.

Lass dich von der Menge nicht verunsichern. Die hat meist
wenig zu sagen. Die meisten werden wohl Folgefehler sein.
Bearbeite den ersten und finde raus, was da schief läuft.
Wenn du ihn behoben hast, fallen dann auch gleich wieder
30 oder 40 Fehler weg.
Also: Immer eins nach dem anderen und nicht verzweifeln.

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

Bewertung
0 lesenswert
nicht lesenswert
> Also auch nicht "typedef struct {
> /* ... */ } vec;" nehmen sondern eben direkt "struct vec { ... };".
> Fuer das typedef gibt es in C++ keinen Grund meh.

Full ack.

> Oder vielleicht noch besser, da das Objekt ja offenbar
> doch ein paar Methoden braucht, gleich "class vec { ... };" schreiben.

Das wissen viele nicht, daher mische ich mich hier mal ein.

Der einzige Unterschied zwischen einer struct und einer class in C++
ist es, dass bei einer struct alle Member per default public sind
und bei einer class sind sie private. Selbiges für Ableitungen.
Struct wird per default public abgeleitet, class wird private.
Ansonsten sind struct und class völlig gleichwertig. Auch eine
struct kann Memberfunktionen beinhalten. Auch eine struct kann
Konstruktor/Destruktor haben. Auch eine struct kann virtuelle
Funktionen haben, etc.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

> Lass dich von der Menge nicht verunsichern.

Keine Sorge Karl, das bestimmt nicht. Ich hatte gestern Abend aber 
einfach kein Bock mehr. Ursache: Ich habe versäumt einen Header 
einzubinden. Jetzt läuft es (ohne const). Nun fehlt bloß noch ein Guru 
der erklärt, warum es mit const nicht ging. Zudem man das hier mal 
probieren sollte:

typedef const struct
{
  unsigned int inge;
  unsigned int walburg;
  const unsigned int* ingeborg;
}STRUKTUR;

Das funktioniert anstandslos. Ist es VC6 (Bug) oder ist es C++ allgemein 
(Inkonsistenz)? Oder DAU?

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

Bewertung
0 lesenswert
nicht lesenswert
T. H. wrote:
>
typedef const struct
> {
>   unsigned int inge;
>   unsigned int walburg;
>   const unsigned int* ingeborg;
> }STRUKTUR;
>
> Das funktioniert anstandslos. Ist es VC6 (Bug) oder ist es C++ allgemein
> (Inkonsistenz)? Oder DAU?

Im Moment tendiere ich zu einem Bug.
Ich hab den C++ Standard nicht hier, kann da erst am Wochenende
reinschauen. Wenn ich Zeit habe, mach ich mich mal über Aggregate
schlau. In meiner Erinnerung ist das etwas schwammig. Auf
Anhieb komme ich aber nicht drauf, wie ein const die Definition
eines Aggregates verändern könnte. Und das mit der Initialisierung
ist ja wohl ein Witz. Gerade weil da const im Spiel ist, muss
initialisiert werden.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre interessant! Worauf ich eigentlich hinaus wollte:

typedef    const    struct
{
   const    unsigned int inge;
   const    unsigned int walburg;
   const unsigned int* ingeborg;
}STRUKTUR;

Funktioniert nämlich nicht. Hat jemand den Borland da?

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

Bewertung
0 lesenswert
nicht lesenswert
T. H. wrote:
> Wäre interessant! Worauf ich eigentlich hinaus wollte:
>
>
>
typedef    const    struct
> {
>    const    unsigned int inge;
>    const    unsigned int walburg;
>    const unsigned int* ingeborg;
> }STRUKTUR;
>
> Funktioniert nämlich nicht.

Das macht aber auch nicht wirklich viel Sinn.
Ob die ganze Struktur const sein soll oder nicht
legt man sinnigerweise erst bei der Definition der
Variablen fest.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber in diesem Fall dürfte er nicht stottern. Die Struktur ist konstant, 
also auch die Elemente. Dennoch stört er sich am const der Integer. Über 
Sinn oder Unsinn dieser Konstruktion sei nur soviel gesagt: In meinem 
Fall macht typdef const struct durchaus Sinn, ich weiss es von Anfang 
an, dass es eine konstante (unabänderbare) Struktur sein sollte und 
nur eine Hilfskonstruktion ist.

Autor: T. H. (pumpkin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe aus Interesse Visual C++ 2005 Express aufgespielt und das Beispiel 
compiliert:

0 Fehler, 0 Warnung(en)
Erstellen: 1 erfolgreich, Fehler bei 0, 0 aktuell, 0 übersprungen

Scheinbar wirklich ein Bug im 6er.

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.