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
typedefstruct{
2
unsignedchar*Tab;
3
uint16_tlength;
4
uint16_tPrio;
5
}sStruct;
Nun lege ich ein Paar "Objekte" an :
1
constsStructsTab1={Tab1,50,1};
2
constsStructsTab2={Tab2,75,2};
3
...
Und möchte diese nun anschließend in einem Array zusammenfassen:
1
constsStruct[]aTab={sTab1,sTab2};
Ich bekomme aber immer nur die Fehlermeldung:
1
error:initializerelementisnotconstant
(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!!!
"Zwischenschritt" ist untertrieben. Du legst die Variablen zwei Mal im
Speicher an. Zuerst sTab1, sTab2 und dann nochmal ein Array mit den
gleichen Daten. Das ist ja vermutlich nicht, was Du haben möchtest?
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...
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.
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
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++!)
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
intmain(){
4
constintx=15;
5
longp=&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
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.
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
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.