Wenn ich diesen nun initialisiere (für die ganze C-Datei)
1
staticparameter_tsparameter[2]=
2
{
3
{LED_1,0,0,},
4
{LED_2,0,0,}
5
};
Hier muss ich für die veränderlichen Variablen ja jetzt eine 0
einsetzen.
Gibt es eine Möglichkeit, die Struktur in einer Init-Funktion erst zu
initialisieren ohne das const zu verlieren?
In C kann man eine const nicht legal nachträglich noch ändern.
Also beim Initialisieren den const-Wert setzen, und in einer
init()-Funktion nicht mehr ändern.
(Auch wenn man versuchen kann, das const wegzucasten - kann gehen, muß
aber nicht und ist nicht schön).
Besser ist es wohl, das Problem anders zu lösen.
Beispielsweise könnte man zur eindeutigen Erkennung nicht eine
eingebaute id nehmen, sondern implizit die Adresse der struct.
Sara schrieb:> Hier muss ich für die veränderlichen Variablen ja jetzt eine 0> einsetzen.
PS:
nein, musst du eigentlich nicht.
Beim Initialisieren könntest du auch nur den jeweils ersten Wert für die
id angeben, und den Rest weglassen.
Dann wird automatisch mit Nullen aufgefüllt.
Die init() könnte dann den Rest machen.
Klaus W. schrieb:> Besser ist es wohl, das Problem anders zu lösen.> Beispielsweise könnte man zur eindeutigen Erkennung nicht eine> eingebaute id nehmen, sondern implizit die Adresse der struct.
Oder index der struct in einem Array.
In der Praxis ist das Problem oft anders herum: Wenn ein Element const
ist, packt der Linker alles ins const-Segment. (Das kann man aber lösen)
Prinzipiell kannst Du auch const-Werte ändern. Es spricht nicht Mal
etwas dagegen. const volatile ist ja auch möglich.
Es muss nur sicher sein, dass kein Programmteil "darauf reinfällt". Und
damit öffnen wir das Feld des U.B.
A. S. schrieb:> In der Praxis ist das Problem oft anders herum: Wenn ein Element> const> ist, packt der Linker alles ins const-Segment. (Das kann man aber lösen)
Nein, nur wenn die Variable selbst, also das "parameter", const ist.
Wäre sonst ein ziemlich nutzloser Linker!
A. S. schrieb:> Prinzipiell kannst Du auch const-Werte ändern.
Aber nur in C. In C++ ist es verboten, und kann zu
UB/Programmabsturz/whatever führen, eben z.B. weil der Linker die
const-Variable (klingt wie gerade Kurve) in einen Read-Only-Bereich
(Flash?) gemappt hat.
Programmierer schrieb:> Aber nur in C. In C++ ist es verboten, und kann zu> UB/Programmabsturz/whatever führen, eben z.B. weil der Linker die> const-Variable (klingt wie gerade Kurve) in einen Read-Only-Bereich> (Flash?) gemappt hat.
Das kann dir in C genauso passieren.
Klaus W. schrieb:> Das kann dir in C genauso passieren.
Da bin ich mir nicht so sicher. IIRC sind const-Daten in C einfach nur
"Variablen die man nicht direkt zuweisen kann", aber sobald man das
const wegcastet, darf man sie verändern.
Programmierer schrieb:> IIRC sind const-Daten in C einfach nur> "Variablen die man nicht direkt zuweisen kann", aber sobald man das> const wegcastet, darf man sie verändern.
Aber der Linker kann sie direkt ins ROM packen. Macht ja dort Sinn, wo
das ROM genauso schnell wie RAM gelesen werden kann.
A. S. schrieb:> Aber der Linker kann sie direkt ins ROM packen.
Ist das vom Standard erlaubt? Macht Compiler/Linker das nicht nur, wenn
er sicher ist dass nirgendwo umgecastet wird, was auch nur dann geht
wenn es "static" ist? Mir ist als wäre da was...
Problem ist wohl, der Standard benutzt "const" für 2 unterschiedliche
Aufgaben.
Als Ersatz für das #define. Hier sollen Compiler, Linker... alle Arten
von Performance Optimierungen machen. Bei denen Zuweisungen und casts
natürlich nicht klappen können.
Als Zusicherung. Die Komponenten, die dein Programm benutzt, werden
deine Daten nicht verändern. In diesem Fall soll beides funktionieren.
Ganz egal, ob du der aufgerufenen Funktion einen const Pointer oder
einen normalen Pointer übergibst.
Noch ein Kommentar schrieb:> Problem ist wohl, der Standard benutzt "const" für 2> unterschiedliche> Aufgaben.>> Als Ersatz für das #define.
Das ist weder für C noch für C++ der Fall. Der Standard ist (auch) da
sehr präzise.
Und eigentlich gibt es auch gar kein Problem.
Oliver
Oliver S. schrieb:> Noch ein Kommentar schrieb:>> Problem ist wohl, der Standard benutzt "const" für 2>> unterschiedliche>> Aufgaben.>>>> Als Ersatz für das #define.>> Das ist weder für C noch für C++ der Fall.
In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,
eine echte Compilezeit-Konstante. In C ist es nur eine Variable, die man
nicht verändern darf.
Programmierer schrieb:> IIRC sind const-Daten in C einfach nur "Variablen die man nicht direkt> zuweisen kann", aber sobald man das const wegcastet, darf man sie> verändern.
Teil 1 stimmt, Teil 2 nicht.
Programmierer schrieb:> A. S. schrieb:>> Aber der Linker kann sie direkt ins ROM packen.>> Ist das vom Standard erlaubt?
Ja. Es ist dem Compiler erlaubt, Sachen die const sind, an Stellen
abzulegen, die keinen Schreibzugriff erlauben. Wobei das bei einer
struct, in der nur eins von mehreren Elementen const ist, in der Regel
nicht passieren wird, da die Elemente nicht einfach auf völlig
unterschiedliche Speicherregionen verteilt werden können.
Es ist dem Compiler auch erlaubt, anzunehmen, dass eine als const
deklarierte Variable niemals verändert wird und basierend auf dieser
Annahme Dinge zu optimieren.
> Macht Compiler/Linker das nicht nur, wenn er sicher ist dass nirgendwo> umgecastet wird, was auch nur dann geht wenn es "static" ist? Mir ist als> wäre da was...
Ein Compiler darf das machen, wenn er will. Der Standard verbietet das
nicht, aber er erfordert es auch nicht. Tatsächlich darf der
Compiler/Linker in dem Fall machen, was er will - undefiniertes
Verhalten eben.
Rolf M. schrieb:>>> Als Ersatz für das #define.>>>> Das ist weder für C noch für C++ der Fall.>> In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,> eine echte Compilezeit-Konstante.
Allerdings kann ein #define natürlich viel mehr, als nur Konstanten zu
definieren. Insofern ist "const" (oder "constexpr") nun nicht wirklich
ein Ersatz. C++ hat sich an anderen Stellen sehr bemüht, den
Präprozessor auch sonst noch vermeidbar zu machen, aber das ist nun
jenseits von "const".
Jörg W. schrieb:> Rolf M. schrieb:>>>> Als Ersatz für das #define.>>>>>> Das ist weder für C noch für C++ der Fall.>>>> In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,>> eine echte Compilezeit-Konstante.>> Allerdings kann ein #define natürlich viel mehr, als nur Konstanten zu> definieren. Insofern ist "const" (oder "constexpr") nun nicht wirklich> ein Ersatz.
Ja, ich bin jetzt davon ausgegangen, dass es nur um diesen einen
spezifischen Anwendungsfall von #define geht. Dass const nicht alle
Anwendungsfälle davon ersetzt, ist eigentlich offensichtlich.
Rolf M. schrieb:> Ja, ich bin jetzt davon ausgegangen, dass es nur um diesen einen> spezifischen Anwendungsfall von #define geht. Dass const nicht alle> Anwendungsfälle davon ersetzt, ist eigentlich offensichtlich
Es ist eher anders rum: const wurde in seiner Bedeutung erweitert, dass
man es als Ersatz für #define nutzen kann. Es ist aber weder notwendig
noch vorgesehen, eine const-Variable zur Compile- oder Linkzeit zu
kennen.
Also erlaubt C++ es dem Compiler, dann (und natürlich nur dann) wenn er
es kennt, den Wert der const Variablen literal zu verwenden.
Wobei man in C++ (anders als in C) einen const-Wert als Größe für eine
Array-Definition benutzen kann (auch auf globaler/statischer Ebene) –
wie soll das gehen, wenn der Wert dem Compiler nicht bekannt ist?
Also
1
constintsize=42;
2
intarray[size];
compiliert in C++, nicht aber in (Standard-)C.
Wenn ich in C++ die Initialisierung entferne, bekomme ich einen Fehler:
1
constintsize;
2
intarray[size];
1
$ c++ -c foo.C
2
foo.C:1:11: error: default initialization of an object of const type 'const int'
A. S. schrieb:> Es ist eher anders rum: const wurde in seiner Bedeutung erweitert, dass> man es als Ersatz für #define nutzen kann. Es ist aber weder notwendig> noch vorgesehen, eine const-Variable zur Compile- oder Linkzeit zu> kennen.>> Also erlaubt C++ es dem Compiler, dann (und natürlich nur dann) wenn er> es kennt, den Wert der const Variablen literal zu verwenden.
Der Punkt ist, dass C++ das dem Compiler nicht nur erlaubt, sondern ihn
im Gegensatz zu C auch dazu verpflichtet.
Jörg W. schrieb:> Wobei man in C++ (anders als in C) einen const-Wert als Größe für eine> Array-Definition benutzen kann (auch auf globaler/statischer Ebene) –> wie soll das gehen, wenn der Wert dem Compiler nicht bekannt ist?
Eben. Oder auch als Template-Parameter, die ausschließlich zur
Compilezeit exitieren.
Rolf M. schrieb:> sondern ihn im Gegensatz zu C auch dazu verpflichtet.
Ich verstehe was Du meinst: muss wenn kann (also soll). Ich hätte "soll"
statt "erlaubt" schreiben müssen.
Es ist jedoch ok, wenn er nicht kann (weil er dann "nicht muss"=nicht
verpflichtet ist). Dann liest er den Wert zur Laufzeit. Oder wirft eine
Fehlermeldung wie bei Jörg, wo er hätte können müssen.
Es soll halt nicht der Eindruck entstehen, dass irgendein Vodoo alle
consts wegoptimiert oder wegoptimieren könnte.
A. S. schrieb:> Es soll halt nicht der Eindruck entstehen, dass irgendein Vodoo alle> consts wegoptimiert oder wegoptimieren könnte.
Da stimme ich dir natürlich zu. Es ist ja auch gar nicht immer möglich
oder sinnvoll, da alles "weg zu optimieren". Einfache Konstanten
allerdings (also irgendwelche Zahlen und dergleichen) lassen sich
allerdings praktisch immer optimieren, und das kann mit "const" eben
auch ein C-Compiler tun.
Sara schrieb:> ich habe eine Struktur... typedef...
Nein, du hast eine Umbenennung. Und zwar von einem Typnamen zu einem
zusätzlichen zweiten Typnamen. (der erste kann auch namenlos sein)
Der entscheidende Punkt ist, daß das alles im Bereich der
Typbezeichnungen ist und nicht im Bereich der Deklaration von Variablen
oder Konstanten. Begreife so etwas mal. Ein Variablentyp ist lediglich
eine Vereinbarung mit dem Compiler. Ob du hingegen später damit eine
Variable oder ein Konstante anlegen willst, ist an dieser Stelle nicht
relevant.
Soviel zum Prinzip.
Nun stelle dir mal vor, daß du mit deinem Typ eine Variable anlegen
willst. Und weil wir hier im mikrocontroller.net sind, stehen da zwei
Medien zur Verfügung: RAM oder ROM(Flash). Wenn es eine Variable sein
soll, dann wird man dort auch einen Wert hineinschreiben wollen. Also
RAM, vielleicht auf dem Stack als lokale Variable oder im Heap. Aber wie
kommt da ein von dir gewünschter konstanter Inhalt hinein? Von Harry
Potter hineingehext? Oder wie stellst du dir so etwas vor?
W.S.
Rolf M. schrieb:> In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,> eine echte Compilezeit-Konstante.
Auch C++ kennt const volatile, und für die wirklich konstanten
Konstanten dann noch constexpr.
Oliver
Oliver S. schrieb:> Auch C++ kennt const volatile, und für die wirklich konstanten> Konstanten dann noch constexpr.
Genau.
Und als Sahnehäubchen sogar mutable. Das macht aus einem const wieder
ein nicht-const :-)
>>>In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,>>>eine echte Compilezeit-Konstante. In C ist es nur eine Variable, die man>>>nicht verändern darf.
stimmt, in der Praxis aber UB => do not use, fertig.
In C mache ich mir keine Gedanken darüber.Globale, statische oder
Stackvariablen lassen sich über {.id = LED1} initialisieren, der Rest
kann später zur Laufzeit gesetzt werden. Bei malloc und anderen
dynamisch Erzeugten Objekten ist das schlicht unbenutzbar.
In C++ gibt es Klassen dafür. Die Kontanten können durch
die Klassenhierarchie durchgereicht werden.
Klaus W. schrieb:> Und als Sahnehäubchen sogar mutable. Das macht aus einem const wieder> ein nicht-const :-)
Nicht so ganz. Es macht etwas nicht-const, auch wenn es Teil von etwas
größerem ist, das eigentlich const ist. Es ist genau für den
entgegengesetzten Fall zu dem im Ursprungsposting.
root schrieb:>>>>In C++ ist es der Fall. Dort ist etwas, das als const definiert ist,>>>>eine echte Compilezeit-Konstante. In C ist es nur eine Variable, die man>>>>nicht verändern darf.>> stimmt, in der Praxis aber UB => do not use, fertig.
Der Punkt ist nicht das UB (das es in C und C++ gleichermaßen gibt),
sondern dass man in C eine const-Variable an den Stellen, wo eine
Compilezeit-Konstante notwendig ist, gar nicht verwenden kann, während
man das in C++ sehr wohl kann.
Rolf M. schrieb:> sondern dass man in C eine const-Variable an den Stellen, wo eine> Compilezeit-Konstante notwendig ist, gar nicht verwenden kann, während> man das in C++ sehr wohl kann.
Auch da ist der Standard sehr präzise: In C++ sind const-Variablen
"constant expressions", in C nicht.
Oliver