Forum: Mikrocontroller und Digitale Elektronik c constVar bei init von struct benutzen


von mrXYZ (Gast)


Lesenswert?

Hallo,

warum funktioniert folgender code nicht?
1
static const char testConst =18;
2
static struct {
3
  char test1;
4
  char test2;
5
} testSC =
6
{
7
  .test1=42, // < OK
8
  .test2=testConst // Error[Pe028]: expression must have a constant value
9
};

von Teddy (Gast)


Lesenswert?

Welcher Compiler und Umgebung?

von Pommes (Gast)


Lesenswert?

... das ist IAR.

@TO:
Welche Version hast Du am Start?

VG, Stephan

von mrXYZ (Gast)


Lesenswert?

IAR 8.50.4,
allerdings meckert der Clang von VS Code das auch an

von MM (Gast)


Lesenswert?

Funktioniert bei mir bei verschiedenen IDEs.

von g4st (Gast)


Lesenswert?

Vermutlich musst du im Compiler C99 aktivieren.

von Programmierer (Gast)


Lesenswert?

Das ist in C grundsätzlich nicht möglich, weil es da keine echten 
Konstanten gibt. "const" bedeutet nur, dass man sie nicht selbst ändern 
darf. So etwas geht in C nur mit enum oder Makros.

In C++ geht es hingegen schon, nur da gibt es die designated 
initializers nicht...

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Eine Variable (in c) ist nun mal keine constant expression, ob da nun 
const davor steht oder nicht, ist egal. In C++ gibt es constexpr für 
sowas (wobei dort auch const etwas anders gehandhabt wird und geht), in 
C leider noch nicht. Da muss man noch auf enums oder macros zurück 
greifen, oder bei dem Anwendungsfall oben, die Variable in einer 
Funktion initialisieren. Viele Compiler haben da auch die 
__attribute__((constructor)) extension, die bei sowas nützlich werden 
kann.

von Rolf M. (rmagnus)


Lesenswert?

g4st schrieb:
> Vermutlich musst du im Compiler C99 aktivieren.

Das ist von der C-Version unabhängig.

Programmierer schrieb:
> In C++ geht es hingegen schon, nur da gibt es die designated
> initializers nicht...

Inzwischen gibt's die dort auch, sind aber noch ziemlich neu:
https://en.cppreference.com/w/cpp/language/aggregate_initialization
Ärgerlicherweise muss man aber zwingend die Reihenfolge aus der 
Typdefinition einhalten, wodurch das Feature wesentlich weniger nützlich 
als in C ist.

von g4st (Gast)


Lesenswert?

Rolf M. schrieb:
> Das ist von der C-Version unabhängig.

Ja, aber mit C99 ("designated initializers") und den - 
compilerabhängigen - Erweiterungen zum ISO Standard funktioniert es dann 
dennoch. Vorausgesetzt natürlich man hat im Compiler keine 
"strict"-Option o. ä. aktiv und der Compiler unterstützt die 
entsprechende Erweiterung.

von Rolf M. (rmagnus)


Lesenswert?

g4st schrieb:
> Rolf M. schrieb:
>> Das ist von der C-Version unabhängig.
>
> Ja, aber mit C99 ("designated initializers") und den -
> compilerabhängigen - Erweiterungen zum ISO Standard funktioniert es dann
> dennoch.

Ok, die designated initializers gibt's erst ab C99.

> Vorausgesetzt natürlich man hat im Compiler keine "strict"-Option o. ä. aktiv
> und der Compiler unterstützt die entsprechende Erweiterung.

Hmm, gcc 9.3 und clang 10 lassen das zu und geben im C99-Modus selbst 
mit -pedantic nicht mal eine Warnung aus. Eigentlich bin ich mir aber 
ziemlich sicher, dass das in C so nicht erlaubt ist. Damit wäre das ein 
Compiler-Bug.

Auch interessant: Wenn man den Initialisierungswert weglässt und damit 
die Variable implizit mit 0 initialisiert wird, bricht der Compiler mit 
Fehler ab, weil es ja keine Compilezeit-Konstante ist.

von mrXYZ (Gast)


Lesenswert?

ok,
ein const ist nicht Konstant, sondern hat nur einen konstanten (nicht 
änderbaren) Wert, von dem der Compiler aber nicht ausgeht das er 
Konstant ist.

Habe es jetzt ganz oldschool mit #define gemacht.

zwei fragen zu den Antworten noch

1)
was würde mir in dem Zusammenhang "__attribute__((constructor))" 
bringen?
So wie ich es verstehe, kann dieses ja nur einmal im Programm verwendet 
werden. Da ich aber ein Modul schreibe, und nicht wissen kann ob es 
nicht ggf. im Hauptprogramm schon verwendet wird, scheidet es für mich 
aus.
Weiterhin wo ist der Vorteil gegenüber einem Aufruf einer init Funtion 
vor der main-while Schleife?

2)
in welchen Fällen wird idealerweise #define, enum, const verwendet?

von Rolf M. (rmagnus)


Lesenswert?

mrXYZ schrieb:
> 1)
> was würde mir in dem Zusammenhang "__attribute__((constructor))"
> bringen?
> So wie ich es verstehe, kann dieses ja nur einmal im Programm verwendet
> werden.

Wie kommst du darauf?

> Weiterhin wo ist der Vorteil gegenüber einem Aufruf einer init Funtion
> vor der main-while Schleife?

Dass du keine init-Funktion in main() aufrufen musst :)

> 2)
> in welchen Fällen wird idealerweise #define, enum, const verwendet?

Da gibt's unterschiedliche Ansichten dazu. In C verwende ich für 
Konstanten immer #define. enum verwende ich - wie der Name schon sagt - 
für Aufzählungstypen, aber nicht, um Einzelkonstanten zu definieren. 
const verwende ich eigentlich nur bei lokalen Variablen, primär um damit 
zu dokumentieren (und sicherzustellen), dass ich den Wert nicht ändern 
will. globale const-Variablen halte ich in C für wenig nutzbringend.

von mrXYZ (Gast)


Lesenswert?

wow,

das geht ja wirklich mit dem __attribute__((constructor)) in mehrerern 
dateien, habe es gerade getestet :) ich hatte es vorher mit dem IAR 
__low_level_init() probiert, wobei dieses nur einmal verwendet werden 
kann

wieder was gelernt, wobei ich erst einmal weiterhin ohne init Funktion 
arbeiten werde.

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.