Forum: Compiler & IDEs C: Array mit als const definierter Größe


von Mike (Gast)


Lesenswert?

Warum akzeptiert der gcc eigentlich folgendes Konstrukt nicht:
1
const uint8_t Size = 10;
2
uint8_t array[Size];

Er scheint nicht zu verstehen, dass Size konstant ist, wie die 
Fehlermeldung vermuten läßt:
 error: variably modified 'array' at file scope

von Mombert H. (mh_mh)


Lesenswert?

Mike schrieb:
> Warum akzeptiert der gcc eigentlich folgendes Konstrukt nicht:const
> uint8_t Size = 10;
> uint8_t array[Size];
>
> Er scheint nicht zu verstehen, dass Size konstant ist, wie die
> Fehlermeldung vermuten läßt:
>  error: variably modified 'array' at file scope

Weil die Sprache das so vorgibt.

von Mike (Gast)


Lesenswert?

Mombert H. schrieb:
> Weil die Sprache das so vorgibt.

Und welchen Sinn hat diese Vorgabe?

von P. S. (namnyef)


Lesenswert?

Mit "const" ist die Size-Variable nur "read-only", aber eben nicht 
"konstant" im Sinne einer "constant expression". Damit definierst du ein 
Array mit variabler Länge, was - je nach Standard - nicht unterstützt 
ist.

: Bearbeitet durch User
von Michael D. (nospam2000)


Lesenswert?

Mike schrieb:
> Warum akzeptiert der gcc eigentlich folgendes Konstrukt nicht:

In C könntest du als Workaround einen Enum verwenden:
enum { N = 5 };
char is[N];

Unter C++ könntest du eine constexpr verwenden, damit geht das.
static const int N=5;
char is[N];

Details siehe hier:
https://stackoverflow.com/questions/18848537/can-a-const-variable-be-used-to-declare-the-size-of-an-array-in-c

 Michael

von A. S. (Gast)


Lesenswert?

Als c++ wäre das ok. In c soll jede Quelle in einem Rutsch kompiliert 
werden können. Das wäre hier zwar möglich, aber nicht wenn die 
Initialisierung erst später oder in einer anderen Quelle erfolgt.

Das Konstrukt für den Zweck  ist #define

von Daniel A. (daniel-a)


Lesenswert?

A. S. schrieb:
> In c soll jede Quelle in einem Rutsch kompiliert
> werden können.

In C++ eigentlich auch.

von Rolf M. (rmagnus)


Lesenswert?

P. S. schrieb:
> Mit "const" ist die Size-Variable nur "read-only", aber eben nicht
> "konstant" im Sinne einer "constant expression". Damit definierst du ein
> Array mit variabler Länge, was - je nach Standard - nicht unterstützt
> ist.

Außerhalb von Funktionen wird es bei keinem Standard unterstützt.

Mike schrieb:
> error: variably modified 'array' at file scope

A. S. schrieb:
> Als c++ wäre das ok. In c soll jede Quelle in einem Rutsch kompiliert
> werden können.

Das soll sie in C++ auch.

> Das wäre hier zwar möglich, aber nicht wenn die Initialisierung erst
> später oder in einer anderen Quelle erfolgt.

Die Konstante kann nur bei ihrer Defintion initialisiert werden. Ein 
Problem wäre es eher, wenn es an der Stelle nur eine Deklaration ist und 
die Definition in einer separat compilierten Datei steht. Das ist aber 
bei C++ ebenfalls so.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Mike schrieb:
> const uint8_t Size = 10;
> uint8_t array[Size];
>
> Er scheint nicht zu verstehen, dass Size konstant ist, wie die
> Fehlermeldung vermuten läßt

Der Compiler hat dir doch ganz ausführlich gesagt, was du falsch 
gemacht hast. Ich formuliere dir dein eigenes Zeug mal so um, daß du es 
besser verstehen kannst:
1
 const unsigned char Size;
2
 Size = 10;
3
 unsigned char array[Size];
4
 ...
Das 'const' bewirkt beim Schreiben für einen µC, daß deine Variable 
nicht im RAM, sondern im Maschinencode (aka Flash) angordnet ist. Damit 
ist sie per se readonly. Beim PC ist sie ebenfalls irgendwo im Code, 
wenngleich auch dieser vom OS in den RAM geladen ist. Ob da ein 
schreibender Zugriff möglich ist, hängt vom OS und dessen 
Sicherheitseinstellungen ab.

Bedenke mal, daß der Preprozessor ein wesentlicher Bestandteil der 
Toolchain ist, sowohl bei C als auch bei C++. Also sollte deine Quelle 
etwa so aussehen:
1
 #define Size 10
2
 unsigned char array[Size];

W.S.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Das 'const' bewirkt beim Schreiben für einen µC, daß deine Variable
> nicht im RAM, sondern im Maschinencode (aka Flash) angordnet ist.

Das mag es bei manchen µCs tun, bei anderen nicht. Das hängt ganz von 
der jeweiligen Toolchain ab. Außerdem ist für die Frage, warum man es 
nicht als Array-Größe verwenden kann, vollkommen irrelevant, ob die 
Variable jetzt in einem RAM oder einem Flash steht.

> Bedenke mal, daß der Preprozessor ein wesentlicher Bestandteil der
> Toolchain ist, sowohl bei C als auch bei C++.

In C++ kann man allerdings den überwiegenden Teil dessen, wofür man in C 
den Präprozessor braucht, auch auf anderem (besserem) Weg erreichen. 
Dazu gehört auch das hier.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dass const in C anders gehandhabt wird als in C++, hat IMHO vor allem
historische Gründe. Ich frage mich aber, ob Probleme (bspw. mit der
Abwärtskompatibilität oder was auch immer) zu erwarten wären, wenn das
C++-const nach C zurückportiert würde, so wie es mit einigen anderen
C++-Features ja bereits geschehen ist.

von Rolf M. (rmagnus)


Lesenswert?

Die andere Frage wäre, ob man es in C++ heute noch so definieren würde. 
Ich denke, dass das nämlich auch nur aus Gründen der 
Abwärtskompatibilität zu C++98 so. Denn mit const kann es halt eine 
Compilezeit-Konstante sein, oder auch nicht. Für richtige 
Compilezeit-Konstanten hat man da constexpr.

von Dirk B. (dirkb2)


Lesenswert?

C99 hat doch aber VLA eingeführt (die dann später optional wurden)

In C++ hatte die nie, da soll man wohl zu std::vector migrieren.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Dirk B. schrieb:
> C99 hat doch aber VLA eingeführt

Für lokale Arrays in Funktionen.

von W.S. (Gast)


Lesenswert?

Rolf M. schrieb:
> Das mag es bei manchen µCs tun, bei anderen nicht. Das hängt ganz von
> der jeweiligen Toolchain ab. Außerdem ist für die Frage, warum man es
> nicht als Array-Größe verwenden kann, vollkommen irrelevant, ob die
> Variable jetzt in einem RAM oder einem Flash steht.

Offenbar verstehst du es nicht.
Also: eine initialisierte Variable im Code wird durch das Laden (oder 
Brennen) des Codes initialisiert und bleibt es auch. Eine wie auch immer 
geartete Variable im RAM muß initialisiert werden und jegliches 
Initialisieren von Variablen ist ein separater Vorgang, der mit der 
Kenntnis der Werte von Konstanten im Compiler nichts zu tun hat. Man 
kann also nicht  die Größe eines Arrays über einen Wert einer Variablen 
(egal ob die nun mal als 'const' spezifiziert wurde oder nicht) 
festlegen. Jedenfalls in C.

W.S.

von Oliver S. (oliverso)


Lesenswert?

W.S. schrieb:
> Offenbar verstehst du es nicht.

Ob da irgendwelche Werte im Flash, um RAM, auf Lochkarte oder in Stein 
gemeißelt werden, spielt überhaupt keine Rolle. Wenn C irgendwann mal 
auf Quantencomputern laufen wird (was es garantiert mal tun wird), 
ändert sich auch nichts.

Die Größe eines Arrays kann in C nicht mit einer const-Varibalen 
definiert werden, weil es der C-Standard so will.

Oliver

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.