Forum: Compiler & IDEs Struct mit Union, Initialisierungsproblem


von Daniel T. (gorni)


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
1
typedef union { 
2
3
  Light l;
4
  Temperature t;
5
6
} sensor_details;
7
8
typedef struct {
9
  
10
  sensortype stype;
11
  sensor_details details;
12
  
13
} sensor_types;

Nun will ich in meiner Main-Funktion diese initialisieren bekomme aber 
folgendes Warning für die Zeile wo type2 initialisiert werden soll:
1
warning: initialization from incompatible pointer type
2
3
sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};
4
Sensor sensor1 = newSensor("TSL235",true,false,0,0,type1,FREQUENCY,timer_init,timer_measure);
5
6
7
sensor_types type2 = {TEMPERATURE,{newtempSensor(DEGREE,0,100)}};
8
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:
1
error: initializer element is not constant
2
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!

von Daniel T. (gorni)


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:
1
sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};

durch diese Zeilen ersetzte:
1
sensor_types type1;
2
type1.stype = LIGHT;
3
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 :
1
sensor_types type1 = {LIGHT,sensor_types.details.l= {newlightSensor(NANOMETRE,0,100)}};

von Rufus Τ. F. (rufus) Benutzerseite


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)

von Oliver (Gast)


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

von Daniel T. (gorni)


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:
1
typedef struct temp_sensor* Temperature;
2
typedef struct light_sensor* Light;
3
4
struct temp_sensor{
5
6
  outputunit unit;
7
  float min_value;
8
  float max_value;
9
};
10
11
struct light_sensor{
12
  
13
  outputunit unit;
14
  float min_value;
15
  float max_value;
16
  float red_part;
17
  float green_part;
18
  float blue_part;
19
};

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.

von df1as (Gast)


Lesenswert?

Daniel T. schrieb:
> Es funktioniert, indem ich diese Zeile:
>
>
1
> sensor_types type1 = {LIGHT,{newlightSensor(NANOMETRE,0,100)}};
2
>
>
> durch diese Zeilen ersetzte:
>
>
1
> sensor_types type1;
2
> type1.stype = LIGHT;
3
> type1.details.l = newlightSensor(NANOMETRE,0,100);
4
>
>
> 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.

von Oliver (Gast)


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?
1
sensor_types type2 = {.stype=TEMPERATURE,.details.t=newtempSensor(DEGREE,0,100)};

wäre die Zeile deiner Wahl gewesen.

Oliver

von Daniel T. (gorni)


Lesenswert?

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

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.