www.mikrocontroller.net

Forum: Compiler & IDEs Struct mit Union, Initialisierungsproblem


Autor: Daniel T. (gorni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allesamt

Ich habe folgendes Problem:

Ich habe ein Struct für Sensoren definiert welches einen Sensortyp in 
Form eines Enums hat und außerdem eine Union, in der 2 Sensorentypen 
enthalten sind
typedef union { 

  Light l;
  Temperature t;

} sensor_details;

typedef struct {
  
  sensortype stype;
  sensor_details details;
  
} sensor_types;


Nun will ich in meiner Main-Funktion diese initialisieren bekomme aber 
folgendes Warning für die Zeile wo type2 initialisiert werden soll:
warning: initialization from incompatible pointer type

sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};
Sensor sensor1 = newSensor("TSL235",true,false,0,0,type1,FREQUENCY,timer_init,timer_measure);


sensor_types type2 = {TEMPERATURE,{newtempSensor(DEGREE,0,100)}};
Sensor sensor2 = newSensor("10kResistor",false,false,0,0,type2,ANALOG,adc_init,adc_measure);


Dieser Fehler tritt aber nur auf wenn ich eine Initialisierung des 
zweiten Sensortyps in sensor_details vornehmen möchte, sprich tausche 
ich die Reihenfolge von Light und Temperature funtkioniert die type1 
Initialisierung nicht.

Definiere ich type1 oder type2 als static bekomme ich die Fehlermeldung:
error: initializer element is not constant
error: (near initialization for type1.details.l)
Diese Meldung weißt auf ein Problem hin was ich schon mehrfach gelesen 
habe, nämlich dass die Initialisierung einer global definierten Union 
zur Compilezeit mit der Zuweisung eines Funktionsaufrufes nicht erlaubt 
ist.

Liege ich komplett auf dem Holzweg, gibt es eine Lösung für das Problem?
Ich befürchte ich denke mal wieder zu kompliziert!

Autor: Daniel T. (gorni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manchmal kommt die Erkenntnis erst wenn man drüber redet/schreibt :-D

Also ich muss wohl noch explizit in der Initialisierung angeben welchem 
Typ in der Union der Funktionsaufruf zugewiesen werden soll, ansonsten 
nimmt der Kompiler immer den ersten Typ an:

Es funktioniert, indem ich diese Zeile:
sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};

durch diese Zeilen ersetzte:
sensor_types type1;
type1.stype = LIGHT;
type1.details.l = newlightSensor(NANOMETRE,0,100);

Macht im Nachhinein auch Sinn, dennoch hätte ich die Zuweisung schon 
gerne in einem Schritt gemacht. Ist das möglich oder funktioniert es nur 
in mehreren Schritten?
So was in der Art :
sensor_types type1 = {LIGHT,sensor_types.details.l= {newlightSensor(NANOMETRE,0,100)}};

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du C++ programmierst, dann könntest Du auch die Möglichkeiten 
nutzen, die C++ bietet. Für Deine unterschiedlichen Initialisierungen 
böten sich unterschiedliche Konstruktoren an; Deine Struktur ist in C++ 
sowieso äquivalent zu einer Klasse.

(der Unterschied zwischen struct und class besteht nur in der 
Default-Anwendung von protected/private/public)

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel T. schrieb:
> warning: initialization from incompatible pointer type

Diese Warnung meint in der Regel genau das, was sie sagt. Da passt ein 
Initialisierungstyp (Pointer) nicht zum Variablentyp. Da du aber nicht 
alle Deklarationen hier zeigst (ich sehe da gar keine pointer), musst du 
das schon selber ergründen.

Allerdings gibt es in der Zeile davor vermutlich (Funktions-)pointer. 
Bist du sicher, daß sich die Warnung nicht auf die Zeile
>Sensor sensor1 = ...
bezieht?

Oliver

Autor: Daniel T. (gorni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@rufus

Ja mittlerweile hab ich so viele Elemente aus der Objektorientierung 
drin, dass es mehr Sinn macht C++ zu nutzen. Aber in anbetracht der mir 
verbleibenden Zeit für dieses Projekt bleibe ich vorerst bei der 
Variante. Vielleicht wird die Version 2 dann umgeschrieben ;-).

Dazu hab ich dann aber gleich eine allgemeine Frage, macht es denn Sinn 
auf einem MCU in C++ zu programmieren? Klar bei den Anforderungen die 
ich im Moment habe wie z.B. Sensorobjekte schon aber betrachtet man dann 
den kompletten Code, ist dieser dann doch wesentlich speicher- und 
leistungsintensiver ?

@Oliver
Ok hab nun nicht den kompletten Code hier reinposten wollen , also in 
der selben Datei sind die beiden Sensortypen Light und Temperatur durch 
Structs und Typedefs definiert, dort findest du dann auch die Pointer 
auf die Structs:

typedef struct temp_sensor* Temperature;
typedef struct light_sensor* Light;

struct temp_sensor{

  outputunit unit;
  float min_value;
  float max_value;
};

struct light_sensor{
  
  outputunit unit;
  float min_value;
  float max_value;
  float red_part;
  float green_part;
  float blue_part;
};

Aber wie schon gesagt warum der Fehler nun entstanden ist habe ich ja 
mittlerweile rausgefunden, im erst genannten Beispiel hat der Compiler 
versucht einem Light Struct ein Temperature Struct zuzuweisen, da ich 
nicht explizit die Zuweisung des richtigen Feldes aus der Union 
vorgenommen habe.

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel T. schrieb:
> Es funktioniert, indem ich diese Zeile:
>
>
> sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};
> 
>
> durch diese Zeilen ersetzte:
>
>
> sensor_types type1;
> type1.stype = LIGHT;
> type1.details.l = newlightSensor(NANOMETRE,0,100);
> 
>
> Macht im Nachhinein auch Sinn, dennoch hätte ich die Zuweisung schon
> gerne in einem Schritt gemacht. Ist das möglich oder funktioniert es nur
> in mehreren Schritten?

Das Kompilat könnte in beiden Fällen gleich aussehen - muss es aber 
nicht. Beim Aggregat wird zuweilen eine vollständige 
Initialisierungskopie gehalten (memcpy), bei 'static' wäre diese Methode 
natürlich ohne Runtime-Overhead.

Ich hatte bei einem GNU-C-Compiler (21020er DSP) immer das Problem, dass 
Aggregatzuweisungen sogar ein Vielfaches des Codes erzeugt hatten. Die 
direkten Einzelzuweisungen lieferten bei Stack-Variablen grundsätzlich 
den kompakteren und damit besseren Code.

Die Aggregatzuweisung ist außerdem zwar vielleicht kompakt im Quellcode, 
auf der anderen Seite sieht man aber auch nicht mehr, was man da tut.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Macht im Nachhinein auch Sinn, dennoch hätte ich die Zuweisung schon
> gerne in einem Schritt gemacht. Ist das möglich oder funktioniert es nur
> in mehreren Schritten?
sensor_types type2 = {.stype=TEMPERATURE,.details.t=newtempSensor(DEGREE,0,100)};

wäre die Zeile deiner Wahl gewesen.

Oliver

Autor: Daniel T. (gorni)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke dir Oliver, hätte nicht gedacht das diese Schreibweise möglich ist 
:-)

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.