Forum: Mikrocontroller und Digitale Elektronik Initializer element is not constant


von Walter T. (nicolas)


Lesenswert?

Guten Abend,

ich habe gerade ein Brett vorm Kopf. Ich will einen konstanten Zeiger 
auf ein Element eines structs erzeugen, weil das für einen 
Funktionsaufruf benötigt wird und ich der Übersicht halber einen 
kürzeren Alias-Namen will.

Sinngemäß so:
1
typedef struct foo_s
2
{
3
    int element0, element1;
4
}
5
foo_t;
6
7
foo_t GlobalStructContainingConfigDataWithALongName = {.element0 = 0, .element1 = 0};
8
9
foo_t *const alias = &GlobalStructContainingConfigDataWithALongName;
10
11
int *const a = &alias->element0;
Allerdings wird vom Compiler für die letzte Zuweisung moniert, dass das 
"initializer element not constant" sei. (Vom ARM-GCC wird es moniert, 
der MinGW-GCC liefert das erwartete Ergebnis ohne Mucken.)

Wo liegt der Denkfehler?

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

int *const p: const pointer to int
int const *q: pointer to const int

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Genau. Ich will einen konstanten Zeiger auf einen veränderlichen Int, 
damit eine Funktion darin als Rückgabewert schreiben kann. Dieser Int 
sollte physisch Element des Structs sein.

Wenn ich es direkt mache, ist alles in Ordnung, also so:
1
int *const b = &GlobalStructContainingConfigDataWithALongName.element0;

Aber über den Alias will er nicht.

: Bearbeitet durch User
Beitrag #7241974 wurde vom Autor gelöscht.
von (prx) A. K. (prx)


Lesenswert?

Initializer müssen Konstanten sein. Die Adresse einer Variablen ist eine 
Konstante, ihr Inhalt ist es nicht. Auch dann nicht, wenn darin irgendwo 
"const" beteiligt ist, weil "const" in C keine Konstanten kennzeichnet, 
sondern Variablen, die nicht verändert werden. NB: In C++ ist das 
anders, weshalb es da auch keinen Fehler gibt.

Das erklärt, weshalb es in avr-gcc nicht funktioniert.

Irgendwo auf dem Weg zwischen dem vmtl recht alten avr-gcc und dem vmtl 
recht neuen MingW wird sich die Sprachvariante von C dahingehend 
verändert haben. Ob per Standard, oder bloss im gcc, habe ich gerade 
nicht parat.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Okay, Du bist genauso müde wie ich. Es geht ja genau darum, in a und b 
die Adresse des members element0 zu hinterlegen. Bei der Konstanten b 
klappt es, bei der Konstanten a nicht.
1
int *const b = &GlobalStructContainingConfigDataWithALongName.element0; // funktioniert
2
int *const a = &alias->element0; // funktioniert nicht.

Ich suche jetzt schon eine halbe Stunde nach Operator-Prävalenzen und 
sprenkle Klammern ein...
Vielleicht fällt es mir morgen früh selbst auf. Gute Nacht!

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Walter T. schrieb:
> int *const a = &alias->element0; // funktioniert nicht.

Das ist ein Zugriff über die Variable "alias" und somit kein zulässiger 
Ausdruck für eine statische Initialisierung. Dass da "const" steht, 
ändert nichts daran. Weshalb das Keyword "const" etwas irreführend ist. 
Wenn du das als C++ übersetzt, ändert sich die Lage, denn in C++ hat 
"const" nicht genau die gleiche Bedeutung wie in C.

Beispiel: const int N = 10;
In C ist N eine Variable, die du nicht verändern darfst, und kann nicht 
an Stellen verwendet werden, wo eine Konstante verlangt wird. In C 
kannst du N deshalb nicht als "case N:" in einem Switch-Statement 
verwenden. In C++ hingegen schon.

: Bearbeitet durch User
von Walter T. (Gast)


Lesenswert?

Das ist Mist. Dann werde ich wohl zæhneknirschend den Präprozessor 
bemühen müssen.

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Das ist Mist. Dann werde ich wohl zæhneknirschend den Präprozessor
> bemühen müssen.

Genau dafür hat er const wohl neu definiert: um den pràprozessor hier zu 
ersetzen.


(Wenn das schon Mist ist, solltest Du über einen Wechsel zu C++ 
nachdenken)

von Walter T. (Gast)


Lesenswert?

Man wechselt nicht in einem fast 5 Jahre alten Projekt die 
Programmiersprache.

Mein nächstes kleines neues Projekt wird C++, aber Altprojekte werden in 
der Sprache weitergepflegt, in der sie angefangen wurden.

von DerEinzigeBernd (Gast)


Lesenswert?

A. S. schrieb:
> (Wenn das schon Mist ist, solltest Du über einen Wechsel zu C++
> nachdenken)

C99 kennt "designated initializers", wie sie im Codebeispiel auch 
verwendet werden. C++ kennt so etwas erst seit C++20; vermutlich dürften 
die meisten Compiler nicht neu genug dafür sein.

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.