www.mikrocontroller.net

Forum: Compiler & IDEs Initialisierung eines lokalen Arrays mit Konstanten


Autor: C_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

warum funktioniert das Initialisieren von lokalen statischen Variablen 
nicht mit Konstanten?
    static u16 s_u16_buffer[MAX_ANZ][3] ={
            {TempMwInit, TempMwInit, TempMwInit},
            {TempMwInit, TempMwInit, TempMwInit}
    };

MAX_ANZ ist 2
TempMwInit ist eine u16 constante

wenn ich das ganze so initialisiere funktioniert es !!!:
    static u16 s_u16_buffer[MAX_ANZ][3] ={
            {0, 1, 2},
            {3, 4, 5}
    };

Warum??

Vielen Dank!

Autor: C_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Folgende Fehlermeldung erhalte ich vom Compiler:
invalid initializer expression

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C_programmer wrote:

> MAX_ANZ ist 2
> TempMwInit ist eine u16 constante

Leider ist das in C keine Konstante wie in C++, sondern eine Variable 
mit konstantem Wert. Und das macht den Unterschied.

Autor: C_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Leider ist das in C keine Konstante wie in C++, sondern eine Variable
>mit konstantem Wert. Und das macht den Unterschied.

Da komme ich nicht ganz mit!
const u16 TempMwInit = 120;

ist doch eine konstante?

Warum kann ich diese dann nicht als Initialisierer benutzen?
Oder kommt mir da der Prä-Prozessor dazwischen? Der den "Variablennamen" 
nicht auflöst ?!

Danke!

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C_programmer wrote:
>>Leider ist das in C keine Konstante wie in C++, sondern eine Variable
>>mit konstantem Wert. Und das macht den Unterschied.
>
> Da komme ich nicht ganz mit!
>
> const u16 TempMwInit = 120;
> 
>
> ist doch eine konstante?
>
> Warum kann ich diese dann nicht als Initialisierer benutzen?
> Oder kommt mir da der Prä-Prozessor dazwischen? Der den "Variablennamen"
> nicht auflöst ?!

Nö, der Präprozessor löst keine Variablennamen auf.

Du kannst

1) TempMwInit als Makro definieren
2) Per -DTempMwInit auf der Kommandozeile definieren
3) TempMwInit als lokale static-Variable anlegen
4) Einen Konstruktor schreiben (GNU-Erweiterung) und dort von Hand 
initialisieren, bevor main aufgerufen wird.

Johann

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ist doch eine konstante?

Es ist eine Read-Only-Variable (also das, was Karl Heinz schon vermutet
hat). Solche Variablen (die streng genommen gar nicht variabel sind)
dürfen nicht überschrieben werden, haben aber ansonsten alle
Eigenschaften von gewöhnlichen Variablen. Insbesondere könnte so eine
Variable auch in einer anderen Übersetzungseinheit definiert und in der
aktuellen mit "extern" deklariert werden. Dann kann der Compiler ihren
(konstanten) Wert nicht kennen.

Um solche und ähnliche Probleme zu umgehen, dürfen Variablen (auch
Read-Only-Variablen) generell nicht als Initialisierer von statischen
Variablen verwendet werden. Dort sind nur "direkte" (also lokal
auflösbare) Konstanten erlaubt. Dazu zählen numerische Literale (z.B. 3,
-2.5e-3 usw.), String-Literale, konstante Ausdrücke (z.B. 3+4,
"Text"[3], sizeof-Ausdrücke usw.).

Solche Ausdrücke dürfen auch in Makros verpackt werden. Das ist auch der
gängige Weg, Konstanten mit Namen zu definieren (s. Vorschlag 1 von
Johann).

Johann L. schrieb:

> 3) TempMwInit als lokale static-Variable anlegen

Sicher? Da hast du doch wieder das Problem, dass eine Variable als
Initialisierer verwendet wird.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es numerische Konstanten sind, empfiehlt die Bibel (K&R), statt 
#define lieber enum zu benutzen:
/* Nicht: */
#define AAA 1
#define BBB 2

/* sondern: */
enum {
  AAA = 1,
  BBB = 2
};

Hat dann den Vorteil, dass der Compiler die auch als benannte Konstanten 
(und nicht als Literale) sieht, sagt K&R.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu wrote:
> Johann L. schrieb:
>
>> 3) TempMwInit als lokale static-Variable anlegen
>
> Sicher? Da hast du doch wieder das Problem, dass eine Variable als
> Initialisierer verwendet wird.

Ja, jetzt bin ich sicher. Es geht nämlich auch nicht als static const 
;-)

Sven P. wrote:
> Wenn es numerische Konstanten sind, empfiehlt die Bibel (K&R), statt
> #define lieber enum zu benutzen:
> [...]
> Hat dann den Vorteil, dass der Compiler die auch als benannte Konstanten
> (und nicht als Literale) sieht, sagt K&R.

Kommt auf die Anwendung an. An Makros ist nett, daß man sie überprüfen 
kann, etwa in
#if F_CPU % IRQS_PER_SECOND != 0
#warning Timer arbeitet ungenau!
#endif

#if F_CPU / IRQS_PER_SECOND > 0xff
#error Timer ist nur ein 8-Bit Timer
#endif

Mit enums geht das nicht, weil es leider immer noch kein
__builtin_error ("Hier ist ein Fehler");
gibt, das man zusammen mit builtin_choose_expr verwenden könnte (und 
wenn, ist's "nur" GNU-C).

Die Typisierung bei Enums kann hilfreich sein (Typprüfungen, Warnungen 
bei switch), oder aber nerven, weil's schlechten Code gibt, z.B. in 
Zusammenhang mit -fshort-enums.

Ich verwende beides, Enums und Makros. Immer das, was am besten passt 
:-)

Johann

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:
> Kommt auf die Anwendung an. An Makros ist nett, daß man sie überprüfen
> kann, etwa in
Das is auch wieder wahr.

> Mit enums geht das nicht, weil es leider immer noch kein[...]
Ist aber nicht mit bedingter Kompilierung zu verwechseln -- auch da 
tendiert der K&R zu ganz gewöhnlichen if() {} und verweist auf den 
Optimierer :-)

> Die Typisierung bei Enums kann hilfreich sein
...wenn sie denn benutzt würde grins abgesehen von switch() mein ich 
(in C, in C++ sieht das schon anders aus).

Autor: c_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, das habe ich jetzt verstanden!
Danke an Alle!

Leider ist es nicht möglich, dass ich den Wert per Define anlege, da der 
Initialisierungsparameter aus einem C-File kommt, welches separat 
ausgetauscht werden kann (Flash Parameter).

In der Header-Datei ist diese Variable als extern deklariert und in dem 
entsprechenden C-File definiert.

Also blieb mir nichts anderes übrig, als den 2D Puffer modul-global zu 
machen und in der Init Funktion des Moduls den Puffer mit dem 
Initialisierungswert zu initialisieren.

Aber danke! Jetzt weiß ich zumindest warum Ansatz 1 falsch war! :-)

Wieder was gelernt!

Ciao!

Autor: c_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, noch ein Hinweis, warum ich so ein großes "Drum-Herum" um diese 
Initialisierung mache.

Also bei dem Puffer handelt es sich um einen Puffer für einen einfachen 
digitalen Filter. Aber der Filter muss halt mit etwas vernünftigem 
Initialisiert sein, ansonsten ist die "Einschwingzeit" zu groß.

Und mit dem Initialisierungswert aus dem separaten C-File wird eben 
dieser Filter sozusagen konfiguriert.

Ciao

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann initialisiere den Puffer doch einfach mittels Zuweisungen, dann
hast du die ganzen Probleme nicht.

Autor: c_programmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Dann initialisiere den Puffer doch einfach mittels Zuweisungen, dann
>hast du die ganzen Probleme nicht.

Das habe ich ja damit gemeint, also mit der Initialisierung in der Init 
Funktion des Moduls. Dort habe ich es dann über einmalige Zuweisungen 
gelöst.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.