Initializer element is not constant

OP #7241960
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?
OP #7241969
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.
Beitrag #7241974 wurde von einem Moderator gelöscht.
#7242000
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.
OP #7242006
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!
#7242012
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.
Gast #7242193
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.
Gast #7242257
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.

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