AVR: Problem mit array of structs

OP #2996629
Lesenswert?

Moin,

irgendwie stehe ich gerade komplett auf der Stelle... Also, ich habe 
Tabellen im Rom stehen (per PROGMEM) (z.B. const unsigned char Tab1[] 
PROGMEM = {...})
Nun habe ich ein Struct, welches einen Pointer auf die Tabellen 
beinhalten soll, sowie ein paar andere Daten:

1
typedef struct {
2
    unsigned char *Tab;
3
    uint16_t length;
4
    uint16_t Prio;
5
} sStruct;

Nun lege ich ein Paar "Objekte" an :
1
const sStruct sTab1= {Tab1, 50, 1};
2
const sStruct sTab2= {Tab2, 75, 2};
3
...

Und möchte diese nun anschließend in einem Array zusammenfassen:
1
const sStruct[] aTab = {sTab1, sTab2};

Ich bekomme aber immer nur die Fehlermeldung:
1
error: initializer element is not constant
(Zeilennummer von "const sStruct[] aTab = {sTab1, sTab2};")

Ich steige da gerade nicht durch - wo ist denn da der Fehler???

Vielen Dank für Eure Hilfe!!!
OP #2996760
Lesenswert?

Hm,

also wenn ich das
1
const sStruct sTab1= {Tab1, 50, 1};
2
const sStruct sTab2= {Tab2, 75, 2};
3
...
weglasse, und gleich
1
const sStruct[] aTab = {{Tab1, 50, 1}, {Tab2, 75, 2}};
schreibe, geht es ohne Probleme. Warum also mit dem Zwischenschritt 
nicht???
#2996851
Lesenswert?

Oz zy schrieb:
> Ja, stimmt schon, vom Speicher her ist das besch*** (Pointer wäre da
> wohl besser). Trotzdem interessiert es mich immer noch, warum es nicht
> geht. Eigentlich nur noch für mich...


Weil das keine Konstante ist.
Achtung: Auch wenn du das ganze Zeugs als const markierst, ist das keine 
Konstante. const bedeutet in C NICHT, dass du eine Konstante definierst, 
sondern nur, dass du per Programm den Wert nicht ändern kannst.

Was du geschrieben hast, ist im Grunde

   int i = 5;
   int j = i;

und i ist nun mal keine compile Time Konstante. Noch nicht mal dann, 
wenn du sie als const markierst.

Der Compiler will an dieser Stelle compile-time Konstante sehen. Also: 
Zahlenwerte, Adressen, Stringliterale. Alles andere sind keine 
Konstante.
#2996861
Lesenswert?

Karl Heinz Buchegger schrieb:

> Was du geschrieben hast, ist im Grunde
>
>    int i = 5;
>    int j = i;
>
> und i ist nun mal keine compile Time Konstante. Noch nicht mal dann,
> wenn du sie als const markierst.
>
> Der Compiler will an dieser Stelle compile-time Konstante sehen. Also:
> Zahlenwerte, Adressen, Stringliterale. Alles andere sind keine
> Konstante.

Sicher?

http://de.wikibooks.org/wiki/C-Programmierung:_Variablen_und_Konstanten

Der Nachteil der Definition von Konstanten mit define ist, dass dem 
Compiler der Typ der Konstante nicht bekannt ist. Dies kann zu Fehlern 
führen, die erst zur Laufzeit des Programms entdeckt werden. Mit dem 
ANSI-Standard wurde deshalb die Möglichkeit von C++ übernommen, eine 
Konstante mit dem Schlüsselwort const zu deklarieren. Im Unterschied zu 
einer Konstanten, die über define definiert wurde, kann eine Konstante, 
die mit const deklariert wurde, bei älteren Compilern Speicherplatz wie 
Variablen auch verbrauchen. Bei neueren Compilern wie GCC 4.3 ist die 
Variante mit const immer vorzuziehen, da sie dem Compiler ein besseres 
Optimieren des Codes erlaubt und die Kompiliergeschwindigkeit erhöht.


mfg Andreas
#2996886
Lesenswert?

Andreas B. schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Was du geschrieben hast, ist im Grunde
>>
>>    int i = 5;
>>    int j = i;
>>
>> und i ist nun mal keine compile Time Konstante. Noch nicht mal dann,
>> wenn du sie als const markierst.
>>
>> Der Compiler will an dieser Stelle compile-time Konstante sehen. Also:
>> Zahlenwerte, Adressen, Stringliterale. Alles andere sind keine
>> Konstante.
>
> Sicher?

Ja, sicher.

> http://de.wikibooks.org/wiki/C-Programmierung:_Variablen_und_Konstanten

Wer alleine sowas schreibt
1
Mit dem ANSI-Standard wurde deshalb die Möglichkeit von C++ übernommen,
2
eine Konstante mit dem Schlüsselwort const zu deklarieren.
3
Im Unterschied zu einer Konstanten, die über define definiert wurde ...

zeigt schon, dass er da einige Dinge nicht wirklich verstanden hat.

> Der Nachteil der Definition von Konstanten mit define ist,

#define definiert keine Konstanten sondern Textersetzungen. #define hat 
mit 'Konstanten' nicht das geringste zu tun.


const verhindert, dass du dieses hier tun kannst

   const int i = 5;

   ...
   i = 8;

das ist aber auch schon alles. In C ist i nicht gleichwertig mit einer 
compile-time Konstanten. const Variablen sind Variablen, die man nicht 
(legal) verändern kann. Aber nichts desto trotz sind es immer noch 
Variablen und keine compile-time Konstanten. Bei der Benutzung als 
Initializer Elemente tritt dieser Unterschied beispielsweise zu Tage, 
die in C compile time Konstante sein müssen (nicht jedoch in C++!)
#2996911
Lesenswert?

Karl Heinz Buchegger schrieb:
> das ist aber auch schon alles. In C ist i nicht gleichwertig mit einer
> compile-time Konstanten. const Variablen sind Variablen, die man nicht
> (legal) verändern kann. Aber nichts desto trotz sind es immer noch
> Variablen und keine compile-time Konstanten. Bei der Benutzung als
> Initializer Elemente tritt dieser Unterschied beispielsweise zu Tage,
> die in C compile time Konstante sein müssen (nicht jedoch in C++!)

War wohl zu schnell, ja du hast recht. Und ja, ich habe was mit C++ 
durcheinander gebracht, muss das ganze nochmals genauer anschauen.

Auf jeden Fall noch ein kleiner Test:
1
#include <stdio.h>
2

3
int main() {
4
  const int x = 15;
5
  long p = &x;
6
  int * y = p;
7

8
  *y = 30;
9
  
10
  printf("%i\n", x);
11
}

Jaa, dieser Code gibt 30 aus. auch mit -O3.

Man lernt nie aus;-)


mfg Andreas
#2996937
Lesenswert?

Andreas B. schrieb:


> Jaa, dieser Code gibt 30 aus. auch mit -O3.

Samt einer Warnung
(zumindest sollte das eine Warnung geben)

Und ja, er könnte auch 15 ausgeben. Je nachdem, wie gut der Compiler 
aufgelegt ist. Denn im Grunde hast du hier einen illegal Cast (auch wenn 
du ihn selbst nicht geschrieben hast) und damit werden keine Wetten mehr 
angenommen, welches das richtige Ergebnis ist :-)

In dem Moment, in dem du
  const int x = 15;
schreibst, darf der Compiler diese Zusicherung von dir verwenden (er 
darf, aber er muss nicht).
Deine Zusicherung lautete: x hat den Wert 15 und dieser Wert wird sich 
nicht verändern (daher auch das const). Nur: Wenn du das zusicherst, 
dann solltest du dich auch daran halten und x nicht mehr auf Umwegen 
verändern. Sonst kann das Ärger geben.
#2997151
Lesenswert?

Karl Heinz Buchegger schrieb:
> Andreas B. schrieb:
>
>
>> Jaa, dieser Code gibt 30 aus. auch mit -O3.
>
> Samt einer Warnung
> (zumindest sollte das eine Warnung geben)

Mehr als eine, schon klar;-)

>
> Und ja, er könnte auch 15 ausgeben. Je nachdem, wie gut der Compiler
> aufgelegt ist. Denn im Grunde hast du hier einen illegal Cast (auch wenn
> du ihn selbst nicht geschrieben hast) und damit werden keine Wetten mehr
> angenommen, welches das richtige Ergebnis ist :-)
>
> In dem Moment, in dem du
>   const int x = 15;
> schreibst, darf der Compiler diese Zusicherung von dir verwenden (er
> darf, aber er muss nicht).
> Deine Zusicherung lautete: x hat den Wert 15 und dieser Wert wird sich
> nicht verändern (daher auch das const). Nur: Wenn du das zusicherst,
> dann solltest du dich auch daran halten und x nicht mehr auf Umwegen
> verändern. Sonst kann das Ärger geben.

Ich wollte nur feststellen ob der Wert immer noch als Speicheradresse 
verfügbar ist, oder ob dieser vom Optimizer ggf. irgendwo eingesetzt 
wird.

Ich beschäftige mich öfters mit solchen Themen, und der Optimizer macht 
beim GCC doch noch einiges...

Und ich lerne immer mal wider etwas dazu...

z.B. wenn ich diesen Code (ok, incl. 2 Casts) mit dem g++ kompiliere 
wird 15 ausgegeben. Also hier wird tatsächlich eingesetzt.

Also ist es hier keine Variable mehr. DAS hätte ich erwartet, auch vom 
GCC...


mfg Andreas
Persönliche Seite #2997209
Lesenswert?

Andreas B. schrieb:
> Ich beschäftige mich öfters mit solchen Themen, und der Optimizer macht
> beim GCC doch noch einiges...

Was soll das bringen, rauszuklamüstern, wie ein Compiler Code übersetzt, 
der undefined oder unspecified behavior hat?

Selbst wenn er so übersetzt wird wie du dir ausmalst, hat das keinerlei 
Allgemeingültigkeit für andere Compiler, Compilerversionen oder 
-schalter.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren