Forum: Compiler & IDEs C: Konstante weak definieren


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

gibt es für konstante Variablen in C (GCC) ähnliche Möglichkeiten, wie 
eine  "weak"-Deklaration für Funktionen?

Ich will in einer .c-Datei ein "Default" einer 
(struct)-Konfigurationsvariablen anlegen, die aber in einer anderen 
Datei überschreiben können.

Im Notfall könnte ich aus der const-Variablen eine normale Variable 
machen, und eine Initialisierungsfunktion "weak" machen. Aber das wäre 
irgendwie unschön, zumal die const-Variable im Flash liegen kann.

Alternativ kann ich die Initialisierungswerte in ein Präprozessor-Define 
packen und dann mit #ifdef prüfen, ob es nicht schon anderweitig 
vordefiniert wurde. Was mir daran nicht gefällt, ist dass der Header, in 
dem dieser vorrangige #define eventuell steht, auch #includieren muss, 
wenn er eigentlich gar nicht existieren müsste. Ausserdem wären dann die 
Deklaration des Structs und die Definition im #define getrennt, was auch 
eine nette Fehlerquelle ist.

Oder geht es noch schöner?

Viele Grüße
W.T.

: Gesperrt durch Moderator
von jemand (Gast)


Lesenswert?


von Walter T. (nicolas)


Lesenswert?

In der Doku finde ich "weak" nur als Attribut für Funktionen.

Natürlich habe ich es ausprobiert, ob es auch für Variablen geht, und 
ich diesen Teil nicht in der Doku finde.

Deklariere ich eine Variable als "weak", z.B. so:
1
const Menudimension_t Menudimension_messagebox __attribute__((weak)) =
2
{
3
    .Area = {0, 0, GFX_MAX_WIDTH_PX, GFX_MAX_HEIGHT_PX},
4
    .headheight = 2*GFX_MAX_HEIGHT_PX/3,
5
    .scrollbarWidth = 0,
6
    .margin = 0,
7
    .textIndent = 2,
8
    .cornerRadius = 0,
9
    .headsep = -4,
10
};

so wird interessanterweise keine Compiler-Warnung erzeugt (GCC 5.1.0), 
aber aus dem Struct auch nur noch Unsinn ausgelesen. Wird dann eine 
zweite Definition des Structs erzeugt, also:
1
const Menudimension_t Menudimension_messagebox __attribute__((weak)) =
2
{
3
    .Area = {0, 0, GFX_MAX_WIDTH_PX, GFX_MAX_HEIGHT_PX},
4
    .headheight = 2*GFX_MAX_HEIGHT_PX/3,
5
    .scrollbarWidth = 0,
6
    .margin = 0,
7
    .textIndent = 2,
8
    .cornerRadius = 0,
9
    .headsep = -4,
10
};
11
12
const Menudimension_t Menudimension_messagebox =
13
{
14
    .Area = {0, 0, GFX_MAX_WIDTH_PX, GFX_MAX_HEIGHT_PX},
15
    .headheight = 2*GFX_MAX_HEIGHT_PX/3,
16
    .scrollbarWidth = 0,
17
    .margin = 0,
18
    .textIndent = 2,
19
    .cornerRadius = 0,
20
    .headsep = -4,
21
};
kommt erwartungsgemäß der Compiler-Fehler "error: redefinition ....".

Unterm Strich heisst das für mich: Der "weak"-Mechanismus scheint nur 
für Funktionen und nicht für Variablen/Konstanten zu funktionieren.

: Bearbeitet durch User
von Stephan (Gast)


Lesenswert?

Dein Forschergeist in Ehren, aber ist CONST als WEAK nicht ein 
konzeptueller Alptraum?
Was spricht gegen eine normale Variable, die Du default (der CONST-Fall) 
füllst und bei Bedarf (und nachvollziehbar) abänderst? Könntest die 
Veränderung sogar über ein strukturelement (Z.B. .isDefaultInit) 
vermerken)

von A. S. (Gast)


Lesenswert?

Mit libraries geht es vielleicht: wenn Du dein Default einzeln in eine 
lib legst, kannst Du im Projekt eine zweite Instanz definieren, die die 
erste "überschreibt". Natürlich nur metaphorisch, die aus der lib wird 
nicht dazugelinkt.

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Ich will in einer .c-Datei ein "Default" einer
> (struct)-Konfigurationsvariablen anlegen, die aber in einer anderen
> Datei überschreiben können.

Mach das doch einfach. Und um das Default im .c ein #if. Dann brauchts 
im Header nur ein Schalter.

von jemand (Gast)


Lesenswert?

Das GCC-Manual sagt, dass weak auch mit Variablen geht.

https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Variable-Attributes.html#Variable-Attributes

Wenn ich dein Test oben richtig verstehe, hast du die gleiche Variable 
in einer Datei zweimal definiert? Das dürfte auch mit weak-Attribut ein 
Fehler sein (da das weak für den Linker ist, wenn ich mich nicht irre).

von jemand (Gast)


Lesenswert?

Stephan schrieb:
> Dein Forschergeist in Ehren, aber ist CONST als WEAK nicht ein
> konzeptueller Alptraum?
> Was spricht gegen eine normale Variable, die Du default (der CONST-Fall)
> füllst und bei Bedarf (und nachvollziehbar) abänderst? Könntest die
> Veränderung sogar über ein strukturelement (Z.B. .isDefaultInit)
> vermerken)

Beides ist schwer nachvollziehbar, wenn man es versteckt. Const gibt 
aber etwas mehr Garatien, daher würde ich das persönlich eher vorziehen.

von Udo S. (urschmitt)


Lesenswert?

Ich bin zwar schon lange aus der Übung bzgl. c(++), aber wenn ich mir 
die Doku anschaue (Link im 2. Post) dann schreiben die:
"The weak attribute causes the declaration to be emitted as a weak 
symbol rather than a global. This is primarily useful in defining 
library functions which can be overridden in user code, though it can 
also be used with non-function declarations. Weak symbols are supported 
for ELF targets, and also for a.out targets when using the GNU assembler 
and linker. "

Was ich lese, dass es auch für Variablen geht.
Das es nicht innerhalb einesC Files für ein ELF Target geht, sondern nur 
wenn man ein Symbol einer Lib oder einer Objektdatei ausserhalb 
"überschreiben" will.

Was mir jetzt aber nicht klar ist. Wenn ich so eine Konstante benutze um 
in der lib in der sie definiert wurde andere Konstanten oder Werte zu 
definieren die der Compiler dann berechnet, wie wirkt sich das aus, wenn 
die Konstante dann redefiniert wird? Dann müsste der Linker ja auch die 
abhängigen Werte in der eingebundenen library neu berechnen.

: Bearbeitet durch User
von jemand (Gast)


Lesenswert?

Udo S. schrieb:
> Was mir jetzt aber nicht klar ist. Wenn ich so eine Konstante benutze um
> in der lib in der sie definiert wurde andere Konstanten oder Werte zu
> definieren die der Compiler dann berechnet, wie wirkt sich das aus, wenn
> die Konstante dann redefiniert wird? Dann müsste der Linker ja auch die
> abhängigen Werte in der eingebundenen library neu berechnen.

Ich vermute, dass dann beide Definitionen gemischt werden. Also der 
Compiler immer die weake Definiton nutzt.

Interessanterweise gibt es dieses Problem in C++ nicht, da es 
Unterschiede bei const in C vs. C++ gibt: 
https://stackoverflow.com/a/19492225 . In C++ gehen weak und const dann 
einfach nicht zusammen.

Vll lohnt es sich weakref mal anzuschauen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stephan schrieb:
> aber ist CONST als WEAK nicht ein konzeptueller Alptraum?

Sehe ich auch so.

Der Sinn darin, eine Variable als "const" zu deklarieren ist doch, dass 
der Compiler (und nicht erst der Linker) darauf Optimierungen anwenden 
kann, denn er muss nicht mehr davon ausgehen, dass sich deren Wert 
jenseits der (für ihn sichtbaren) Initialisierung nochmal ändert.

Indem man eine Variable als weak deklariert, will man allerdings 
explizit, dass der exakte Wert erst nach dem Linken zur Verfügung steht. 
Damit darf der Compiler Zugriffe auf diese auf keinen Fall bereits zur 
Compilezeit optimieren.

von A. S. (Gast)


Lesenswert?

Udo S. schrieb:
> Wenn ich so eine Konstante benutze um in der lib in der sie definiert
> wurde andere Konstanten oder Werte zu definieren die der Compiler dann
> berechnet, wie wirkt sich das aus, wenn die Konstante dann redefiniert
> wird?

Der C-Compiler rechnet nicht mit Konstanten. Er bildet nicht Mal die 
Adressen.

von Maxe (Gast)


Lesenswert?

Naja, Optimierung ist ja nicht alles. Entscheidender scheint mir, dass 
die Konstanten irgendwo im Code verstreut ueberschrieben sein koennen, 
es also schwer zu ueberblicken ist.

"The weak attribute causes the declaration to be emitted as a weak 
symbol rather than a global."
Hat das Einfluss auf den Scope?

von Walter Tarpan (Gast)


Lesenswert?

Ich kann verstehen, dass "const" und "weak" für den Compilerbauer ein 
Alptraum sind. Aber das dürfte für die Kombination "extern const" doch 
auch schon zutreffen?

von A. S. (Gast)


Lesenswert?

Walter Tarpan schrieb:
> Aber das dürfte für die Kombination "extern const" doch
> auch schon zutreffen?

nur wenn er die Konstanten Variablen auch schon zur Compilezeit 
auswerten soll. C tut das nicht. Ansonsten ist es egal ob extern oder 
extern const, nur das halt kein Schreibzugriff erlaubt ist.

Und auch const volatile stellt kein Problem dar, falls Du das meintest.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. S. schrieb:
> C tut das nicht.

Stell doch bitte nicht pauschal solche Behauptungen auf.
1
$ cat foo.c
2
extern const int i;
3
const int i = 42;
4
5
int get_i(void)
6
{
7
        return i;
8
}
9
$ cc -O -Wall -Wextra -S foo.c
10
$ cat foo.s
11
        .file   "foo.c"
12
        .text
13
        .globl  get_i
14
        .type   get_i, @function
15
get_i:
16
.LFB0:
17
        .cfi_startproc
18
        movl    $42, %eax
19
        ret
20
        .cfi_endproc
21
.LFE0:
22
        .size   get_i, .-get_i
23
        .globl  i
24
        .section        .rodata
25
        .align 4
26
        .type   i, @object
27
        .size   i, 4
28
i:
29
        .long   42
30
        .ident  "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
31
        .section        .note.GNU-stack,"",@progbits

von A. S. (Gast)


Lesenswert?

Jörg W. schrieb:
> Stell doch bitte nicht pauschal solche Behauptungen auf.

dass der Gnu C++ Compiler das soll und der Gnu-C das innerhalb einer 
Datei kann, geschenkt. Es bleibt dennoch eine in C nicht vorgesehene 
(und natürlich nicht verbotene) Optimierung. Wenn er das nicht tut, ist 
es OK. Wenn er das bei weak auch macht, ist es falsch.

In einer normalen Lib (ohne weak) gibt es mit der Implementierung auch 
kein Problem, weil beide nur zusammen zugelinkt werden.

Es ging darum, dass es zu keinem Problem bei verschiedenen Dateien 
führt, weil

> C tut das nicht.

Und wenn der Linker das mittlerweile in C trotzdem macht, … dann scheint 
es erst recht kein Problem für den Compiler-Bauer, weil er es ja nicht 
braucht.

Es ging um diese Aussage:

Walter Tarpan schrieb:
> Ich kann verstehen, dass "const" und "weak" für den Compilerbauer ein
> Alptraum sind. Aber das dürfte für die Kombination "extern const" doch
> auch schon zutreffen?

Und das ist halt falsch. const und weak machen nichts anderes, als mit 
einer Lib schon seit Ansi-C (oder früher) geht. Nur dass man ohne weak 
nicht innerhalb einer C-Datei Kirschenpflücken kann.

von mh (Gast)


Lesenswert?

A. S. schrieb:
> Jörg W. schrieb:
>> Stell doch bitte nicht pauschal solche Behauptungen auf.
>
> dass der Gnu C++ Compiler das soll und der Gnu-C das innerhalb einer
> Datei kann, geschenkt. Es bleibt dennoch eine in C nicht vorgesehene
> (und natürlich nicht verbotene) Optimierung.

Welche Optimierung ist denn deiner Meinung nach in C "vorgesehen"? Und 
in welcher Sprache ist das Optimieren von konstanten Ausdrücken im 
Compiler verpflichtend?

von A. S. (Gast)


Lesenswert?

mh schrieb:
> in welcher Sprache ist das Optimieren von konstanten Ausdrücken im
> Compiler verpflichtend?

C++

In C haben const-"Variablen" externe Bindung. Es muss auch 
funktionieren, wenn sie erst zur Laufzeit ausgelesen wird.

In C++ ist sowas erlaubt wie const int n=11; int a[n];. In C geht das 
nicht (selbst wenn gcc das erlauben sollte).

von mh (Gast)


Lesenswert?

A. S. schrieb:
> mh schrieb:
>> in welcher Sprache ist das Optimieren von konstanten Ausdrücken im
>> Compiler verpflichtend?
>
> C++
>
> In C haben const-"Variablen" externe Bindung. Es muss auch
> funktionieren, wenn sie erst zur Laufzeit ausgelesen wird.
>
> In C++ ist sowas erlaubt wie const int n=11; int a[n];. In C geht das
> nicht (selbst wenn gcc das erlauben sollte).

Das ist keine Antwort auf meine Fragen. Mir ist der Unterschied zwischen 
C-const und C++-const bekannt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. S. schrieb:

> dass der Gnu C++ Compiler das soll und der Gnu-C das innerhalb einer
> Datei kann, geschenkt. Es bleibt dennoch eine in C nicht vorgesehene
> (und natürlich nicht verbotene) Optimierung.

Damit ist aber die pauschale Aussage, "wird in C nicht gemacht", 
Quatsch.

Auf mehr wollte ich nicht hinaus: selbstverständlich darf auch ein 
C-Compiler ein const-Objekt als unveränderlich annehmen.

> Wenn er das bei weak auch macht, ist es falsch.

Kannst du so auch nicht sagen, denn "weak" ist nichts, was der Standard 
definiert.

Die Dokumentation des Compilers macht dazu auch keine weitere Aussage 
(wurde ja oben schon zitiert).

Letztlich interessiert den Compiler das überhaupt nicht (weder GCC noch 
Clang), wenn man in obigem Code ein "__attribute__((weak))" für die 
Variable einfügt. Der generierte Code bleibt der gleiche.

Ergo: weak und const sollte man tunlichst nicht gemeinsam benutzen.

von Rolf M. (rmagnus)


Lesenswert?

Maxe schrieb:
> Naja, Optimierung ist ja nicht alles.

Wenn die dafür sorgt, dass diese Idee gar nicht erst zuverlässig 
funktioniert, dann ist das erst mal ein k.o.-Kriterium.

> Entscheidender scheint mir, dass die Konstanten irgendwo im Code verstreut
> ueberschrieben sein koennen, es also schwer zu ueberblicken ist.

Das sehe ich auch so. Wenn ich irgendwo im Quellcode eine Definition der 
const-Variablen mit Initialisierung sehe, dann erwarte ich eigentlich 
auch, dass sie diesen Wert hat und ihr nicht hinterrücks ein anderer 
Wert gegeben wird.

A. S. schrieb:
> Jörg W. schrieb:
>> Stell doch bitte nicht pauschal solche Behauptungen auf.
>
> dass der Gnu C++ Compiler das soll und der Gnu-C das innerhalb einer
> Datei kann, geschenkt.

Mit LTO würde es mich nicht wundern, wenn er es auch über 
Quellcode-Dateien hinweg täte.

> Es bleibt dennoch eine in C nicht vorgesehene (und natürlich nicht
> verbotene) Optimierung. Wenn er das nicht tut, ist es OK.

Und genauso ok ist es, wenn er das tut.

> Wenn er das bei weak auch macht, ist es falsch.

weak gibt es in C gar nicht.

> Walter Tarpan schrieb:
>> Ich kann verstehen, dass "const" und "weak" für den Compilerbauer ein
>> Alptraum sind. Aber das dürfte für die Kombination "extern const" doch
>> auch schon zutreffen?
>
> Und das ist halt falsch. const und weak machen nichts anderes, als mit
> einer Lib schon seit Ansi-C (oder früher) geht.

Libs sind in ANSI C auch nicht "vorgesehen".

A. S. schrieb:
> mh schrieb:
>> in welcher Sprache ist das Optimieren von konstanten Ausdrücken im
>> Compiler verpflichtend?
>
> C++

Nein. C++ verpflichtet nicht zu irgendwelchen Optimierungen.

> In C haben const-"Variablen" externe Bindung. Es muss auch
> funktionieren, wenn sie erst zur Laufzeit ausgelesen wird.

Nur wenn sie auch volatile sind. Sonst darf der Compiler da beliebig 
dran rumoptimieren.

> In C++ ist sowas erlaubt wie const int n=11; int a[n];. In C geht das
> nicht (selbst wenn gcc das erlauben sollte).

Und was hat das jetzt mit Optimierung zu tun?

von W.S. (Gast)


Lesenswert?

Jörg W. schrieb:
> Der Sinn darin, eine Variable als "const" zu deklarieren ist doch, dass
> der Compiler (und nicht erst der Linker) darauf Optimierungen anwenden
> kann, denn er muss nicht mehr davon ausgehen, dass sich deren Wert
> jenseits der (für ihn sichtbaren) Initialisierung nochmal ändert.

Nö. Eigentlich ist das eben nicht der Sinn des Ganzen, sondern der Sinn 
(und die Anwendung) ist, daß eben diese "Variable" nicht im RAM 
angeordnet sein soll, sondern im Flash.

Manchmal braucht man genau das genau SO - und zwar derart, daß der 
Compiler daran nichts herum"optimiert".

W.S.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Jörg W. schrieb:
>> Der Sinn darin, eine Variable als "const" zu deklarieren ist doch, dass
>> der Compiler (und nicht erst der Linker) darauf Optimierungen anwenden
>> kann, denn er muss nicht mehr davon ausgehen, dass sich deren Wert
>> jenseits der (für ihn sichtbaren) Initialisierung nochmal ändert.
>
> Nö. Eigentlich ist das eben nicht der Sinn des Ganzen, sondern der Sinn
> (und die Anwendung) ist, daß eben diese "Variable" nicht im RAM
> angeordnet sein soll, sondern im Flash.

Das kann gar nicht die Aufgabe von const sein, aus einem einfachen 
Grund: C als Sprache weiß überhaupt nix von RAM oder Flash.
Mit const sagt man dem Compiler lediglich, dass er annehmen darf, dass 
sich der Inhalt nie ändert. Das ist die einzige Aufgabe von const in C.
Natürlich darf der Compiler bzw. Linker sich das zunutze machen, indem 
er die Variable dann in den Flash legt, sofern das geht. Das ist aber in 
gewissem Sinne auch eine Optimierung.

> Manchmal braucht man genau das genau SO - und zwar derart, daß der
> Compiler daran nichts herum"optimiert".

Dann muss man dem Compiler eben ausdrücklich sagen, dass er das nicht 
tun soll. Genau dafür wäre volatile da.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Nein. C++ verpflichtet nicht zu irgendwelchen Optimierungen.
Das ist technisch korrekt. Aber man könnte "umgangssprachlich" sagen, 
dass es in C++ verpflichtende RVO gibt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Mit const sagt man dem Compiler lediglich, dass er annehmen darf, dass
> sich der Inhalt nie ändert.

Nicht ganz: man sagt ihm, dass er keine Änderungsversuche darauf 
zulassen darf.

Aber "const volatile" ist ganz legal, und auch als Erklärung 
dokumentiert als "maybe modified by hardware".

von Walter T. (nicolas)


Lesenswert?

Was wäre denn für einen Compiler/Compilerbauer der Unterschied zwischen 
"const weak" und "const extern"? In beiden Fällen kann er die Werte erst 
beim Linken einsetzen.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Walter T. schrieb:
> Was wäre denn für einen Compiler/Compilerbauer der Unterschied zwischen
> "const weak" und "const extern"? In beiden Fällen kann er die Werte erst
> beim Linken einsetzen.

Wenn die Variable zweimal definiert ist, einmal mit weak und einmal 
ohne, dann bekommt die ohne den Vorrang. Wenn keine von beiden weak ist, 
gibt es einen Fehler.

von A. S. (Gast)


Lesenswert?

Walter T. schrieb:
> Was wäre denn für einen Compiler/Compilerbauer der Unterschied zwischen
> "const weak" und "const extern"? In beiden Fällen kann er die Werte erst
> beim Linken einsetzen.

Es geht nicht ums einsetzen, da C im Gegensatz zu C++ nicht einsetzt. 
Zumindest nicht braucht.

Es geht darum, ob eine Definition  durch eine zweite ersetzt werden 
darf.

Mit einer lib ist das normal, aber in C immer für ein ganzes C-File, 
also alle Funktionen und variablen darin.

Mit weak auch für einzelne

von A. S. (Gast)


Lesenswert?

Wenn ein C File nur int a und b und Funktion f enthält, dann kann ich im 
Projekt alle drei entweder selber neu definieren oder keine.

Mit weak a könnte ich stattdessen a neu definieren und b und f werden 
aus der lib genommen.

von Walter T. (nicolas)


Lesenswert?

Walter T. schrieb:
> as wäre denn für einen Compiler/Compilerbauer der Unterschied zwischen
> "const weak" und "const extern"? In beiden Fällen kann er die Werte erst
> beim Linken einsetzen.

Die Frage bezieht sich auf die Aussage von Jörg 
Beitrag "Re: C: Konstante weak definieren"

von W.S. (Gast)


Lesenswert?

Rolf M. schrieb:
> Das kann gar nicht die Aufgabe von const sein, aus einem einfachen
> Grund: C als Sprache weiß überhaupt nix von RAM oder Flash.

Denke doch erstmal nach!

Selbstverständlich weiß ein jeder Compiler (auch ein C-Compiler) zu 
unterscheiden zwischen Zeugs, was in den Code kommt und Zeugs, wofür 
lediglich Platz reserviert wird.

Das gehört zu den elementaren Aufgaben eines Compilers!

Begreife mal, daß sogenannte Hochsprachen (POS: problemorientierte 
Sprachen) eben genau zu dem Zweck erdacht worden sind, daß man sich als 
Programmierer nicht mit der Maschinenebene herumschlagen muß, wie das in 
Assembler vonnöten ist. Dein angeblicher Grund ist eine völlig unsinnige 
Annahme, denn es ist nicht die Programmiersprache, sondern der Compiler 
(kurz: die Toolchain), der von Ram und Rom und so weiter wissen muß.

Letztendlich ist es egal, ob der Code in einen Flash im µC oder in ein 
schreibgeschütztes Code-Segment im PC kommt: Wichtig ist nur, daß klar 
ist, ob das eine Variable ist, für die man Platz im schreib- und 
lesbaren Speicher reservieren muß - oder ob das eine Konstante ist, die 
entsprechend ihres Typs ein oder mehrere Bytes groß ist und genau so wie 
die Bytes des Maschinencodes in das Codesegment/Flash hinein kommt. Und 
genau für diese Unterscheidung ist 'const' zuständig.

Rolf M. schrieb:
> Dann muss man dem Compiler eben ausdrücklich sagen, dass er das nicht
> tun soll. Genau dafür wäre volatile da.

Das ist schon das zweite totale Mißverständnis deinerseits!

Nein, der Zweck von 'volatile' ist ein Workaround um den Fakt, daß C 
kein sauberes Modulkonzept kennt und deshalb nicht unterscheiden kann, 
ob ein Stück Code den exclusiven Zugriff auf eine Variable hat oder 
nicht.

Deswegen ist es zum Steuern von eventuellen Optimierungen notwendig, 
Variablen, die sich durch andere Instanzen ändern können (Nachbar-Thread 
oder Hardware oder Interrupt oder mal bloß ein Zugriff per 'extern' von 
einer anderen Quelle aus) so zu kennzeichnen, daß der Compiler für diese 
keine lokale Kopie zwecks Optimierung erzeugt, sondern Lesezugriffe 
immer direkt codiert. Das hat überhaupt nichts mit der Anordnung der 
Variaben/Konstanten im Ram- oder Code-Segment zu tun.

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Nein, der Zweck von 'volatile' ist ein Workaround um den Fakt, daß C
> kein sauberes Modulkonzept kennt und deshalb nicht unterscheiden kann,
> ob ein Stück Code den exclusiven Zugriff auf eine Variable hat oder
> nicht.

Absolut nicht.

Bitte lies dir als erstes mal durch, was der Standard dazu sagt.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Rolf M. schrieb:
>> Das kann gar nicht die Aufgabe von const sein, aus einem einfachen
>> Grund: C als Sprache weiß überhaupt nix von RAM oder Flash.
>
> Denke doch erstmal nach!
>
> Selbstverständlich weiß ein jeder Compiler (auch ein C-Compiler) zu
> unterscheiden zwischen Zeugs, was in den Code kommt und Zeugs, wofür
> lediglich Platz reserviert wird.

Ich hatte ganz bewusst von "C als Sprache" geschrieben, nicht vom 
Compiler. Schade, dass du das übersehen hast.
Natürlich weiß der Compiler, wo er die Daten hinsteckt, aber das ist 
dessen Implementierungsdetail und nicht Bestandteil der Sprache selbst. 
const dagegen ist Bestandteil der Sprache.

> Das gehört zu den elementaren Aufgaben eines Compilers!

Ein Compiler für PC-Anwendungen kann in der Regel gar nichts in einen 
Flash stecken. Es wäre auch überhaupt nicht sinnvoll. Dennoch gibt es 
dort const, und es wird auch genutzt. Und es wurde auch schon bei 
Compilern für DOS benutzt, wo es auch keine Read-Only-Segmente gab.

> Begreife mal, daß sogenannte Hochsprachen (POS: problemorientierte
> Sprachen) eben genau zu dem Zweck erdacht worden sind, daß man sich als
> Programmierer nicht mit der Maschinenebene herumschlagen muß, wie das in
> Assembler vonnöten ist.

Ja, eben. Deshalb definiert die Sprache von sich auch auch nicht so 
Dinge wie Flash und RAM. Darum kümmert sich der Compiler.

> Dein angeblicher Grund ist eine völlig unsinnige Annahme, denn es ist nicht
> die Programmiersprache, sondern der Compiler (kurz: die Toolchain), der von
> Ram und Rom und so weiter wissen muß.

Das bestätigt eher meine Aussage, denn das ist genau das, was ich 
geschrieben habe. Dagegen hast du beim Lesen meines Postings offenbar 
die Sprache mit dem Compiler verwechselt.

> Rolf M. schrieb:
>> Dann muss man dem Compiler eben ausdrücklich sagen, dass er das nicht
>> tun soll. Genau dafür wäre volatile da.
>
> Das ist schon das zweite totale Mißverständnis deinerseits!
>
> Nein, der Zweck von 'volatile' ist ein Workaround um den Fakt, daß C
> kein sauberes Modulkonzept kennt und deshalb nicht unterscheiden kann,
> ob ein Stück Code den exclusiven Zugriff auf eine Variable hat oder
> nicht.

Das ist gelinde gesagt Blödsinn. Mit Modulen hat das überhaupt nichts zu 
tun. Volatile dient dazu, dass alle Zugriffe auf den Speicher auch 
wirklich ausgeführt werden, und das ist hier in diesem Fall 
erforderlich.

> Deswegen ist es zum Steuern von eventuellen Optimierungen notwendig,
> Variablen, die sich durch andere Instanzen ändern können (Nachbar-Thread
> oder Hardware oder Interrupt oder mal bloß ein Zugriff per 'extern' von
> einer anderen Quelle aus) so zu kennzeichnen, daß der Compiler für diese
> keine lokale Kopie zwecks Optimierung erzeugt, sondern Lesezugriffe
> immer direkt codiert.

Das stimmt, abgesehen von "bloß ein Zugriff per 'extern'". Da ist ein 
volatile unnötig. Es ist nur dann erforderlich, wenn ein Zugriff 
außerhalb des normalen Programmflusses passiert, also wie du schon 
schreibst, durch einen Interrupt, durch externe Hardware oder durch 
einen anderen Thread.

> Das hat überhaupt nichts mit der Anordnung der Variaben/Konstanten im Ram-
> oder Code-Segment zu tun.

Natürlich nicht. Das habe ich auch nicht behauptet. Es hat aber damit zu 
tun, dass hier der Wert der const-Variablen quasi nach dem Compilieren 
und beim Linken durch einen anderen ersetzt werden soll. Das 
funktioniert nur, wenn auch darauf zugegriffen wird und der Wert nicht 
z.B. einfach direkt im Code eingesetzt wird. Das kann man mit volatile 
sicherstellen.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Eigentlich ist das eben nicht der Sinn des Ganzen, sondern der Sinn (und
> die Anwendung) ist, daß eben diese "Variable" nicht im RAM angeordnet
> sein soll, sondern im Flash.

Dann wäre das Verwenden von "const" auf einem System ohne Flash (z.B. PC 
mit Windows oder Linux: nur RAM) also ein Fehler?!?

Deine Erklärung ist einfach falsch. "const" sagt dem Compiler, dass der 
Wert dieser Variablen vom Programm nicht geändert werden darf.

Quelle für Deine Behauptung?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

W.S. schrieb:
> Nö. Eigentlich ist das eben nicht der Sinn des Ganzen, sondern der Sinn
> (und die Anwendung) ist, daß eben diese "Variable" nicht im RAM
> angeordnet sein soll, sondern im Flash.

Mal wieder keine Ahnung und zu engstirnig?
Was ist denn mit Prozessoren welche erstmal ihr ganzes Programm per ROM 
Bootloader vom QSPI Flash in den DRAM kopieren und dann vollständig 
daraus laufen?
Offensichtlich ist deine "Argumentation" mal wieder hahnebüchen und 
löchrig!
Jörg hat da schon recht.


Daher bitte ich darum:
W.S. schrieb:
> Denke doch erstmal nach!

Beitrag #6362452 wurde von einem Moderator gelöscht.
von ohne Account (Gast)


Lesenswert?

Rolf M. schrieb:
> weak gibt es in C gar nicht

guter Aspekt; kenne ich nämlich auch nicht ... aber vielleicht haben sie 
es ja im neuesten Standard dazu gekittert.
Außerdem:
https://en.wikipedia.org/wiki/Weak_symbol
Weak symbols are not mentioned by the C or C++ language standards; as 
such, inserting them into code is not very portable.

So gewöhnt man sich schlechten Programmierstil an ;-)

von W.S. (Gast)


Lesenswert?

Rolf M. schrieb:
> Das ist gelinde gesagt Blödsinn. Mit Modulen hat das überhaupt nichts zu
> tun. Volatile dient dazu, dass alle Zugriffe auf den Speicher auch
> wirklich ausgeführt werden, und das ist hier in diesem Fall
> erforderlich.

Das hat aber sehr wohl mit dem fehlenden Modulkonzept zu tun!

Im Grunde könnte der Compiler für jeden Lesezugriff auf eine Variable 
eben auf diese zugreifen. Macht er aber aus Optimierungsgründen oftmals 
nicht.

Jedoch kann ein C-Compiler bei globalen Variablen oder gar 
Hardware-Registern eben nicht feststellen, ob sich der Inhalt eben 
dieser Variable aus Gründen ändern kann, die außerhalb des 
Sichtbereiches der vorliegenden Quelle stehen.

Hätte man in C ein Modulkonzept, was wie in Pascal ganz klar festlegt, 
was irgend eine andere Instanz überhaupt sehen kann und was nicht, dann 
bräuchte man sowas wie 'volatile' überhaupt nicht. Grund: der Compiler 
könnte selbst feststellen, ob in der Zwischenzeit, wo der gerade 
aktuelle Code läuft, von woanders ein Zugriff überhaupt möglich ist oder 
nicht.

In C kann man im Prinzip jede irgendwo vorkommende Variable mit 'extern 
typ name' oder schlichtweg über das Einbinden der .h (sofern dort diese 
Variable erwähnt ist) erreichen. Damit ist der Compiler ausgehebelt, er 
kann nicht feststellen, ob die Variable von woanders her erreichbar ist 
oder nicht.

Und genau DAS ist der eigentliche Punkt.
Du hast bloß nicht gründlich genug nachgedacht.


Und hier haben wir noch einen, der nicht nachgedacht hat:

Frank M. schrieb:
> Dann wäre das Verwenden von "const" auf einem System ohne Flash (z.B. PC
> mit Windows oder Linux: nur RAM) also ein Fehler?!?

Soviel Nicht-Denken-Wollen ärgert mich.

Also für die Langsamdenker mal im Einzelnen:

1. const benötigt eine Wertfestlegung (const double a = 3.1415; ). Ist 
dir dieses klar?

2. und warum benötigt const eine Wertfestlegung? Ist dir der tiefere 
Grund dafür bewußt? Man könnte ja auch per #define a 3.1415 dem 
Augenschein nach dasselbe tun -aber der Augenschein trügt.

3. Der Grund ist, daß diese 3.1415 eben nicht in irgendwelche 
Maschinenbefehle eingebaut wird, sondern tatsächlich eine Variable ist, 
die jedoch im CODE steht. Im Mikrocontroller also im Flash, am PC je 
nach OS in einem schreibgeschützten (oder nicht schreibgeschützten) 
Stück RAM (wäre vom Prinzip her dasselbe wie Flash: R/O und nicht R/W). 
Das ist etwas anderes als das Vereinbaren einer Variablen, für die man 
ja nur Platz reservieren muß. Hast du das jetzt begriffen?

> Deine Erklärung ist einfach falsch. "const" sagt dem Compiler, dass der
> Wert dieser Variablen vom Programm nicht geändert werden darf.

Siehe oben, du liegst falsch. Der Hauptgrund ist, daß diese Variable ein 
Teil des zu erzeugenden Codes wird und nicht, daß der Compiler weiß, daß 
man sie nicht beschreiben darf. Das ist ne Schlußfolgerung, die zwar 
logisch, am PC jedoch oftmal völlig falsch ist. Erinnere dich mal an die 
Zeiten von DOS: dort konnte man const vereinbaren und dennoch drauf 
herumschreiben. Ja, das ging.

> Quelle für Deine Behauptung?
Jede .exe Datei zum Beispiel.

Also begreife mal:
const ist dafür, daß etwas in den Code kommt - und zwar nicht implizit 
in den Maschinenbefehlen, sondern explizit als typisierte und mit Wert 
versehene Variable.
volatile ist dafür, daß man dem Compiler ansagt, daß die Variable auch 
von anderen Instanzen geändert werden kann und der Compiler nicht die 
volle Kontrolle darüber hat - und das ist eine Spätfolge davon, daß in C 
einfach mit Header-Dateien gearbeitet wird, was so ziemlich das 
Gegenteil eines Modulkonzeptes ist und keinerlei Kapselung ermöglicht.

Ist dir das nun klar?
Ich habe nämlich den Eindruck, daß du nur stänkern wolltest.


Jörg W. schrieb:
> W.S. schrieb:
>> Nein, der Zweck von 'volatile' ist ein Workaround um den Fakt, daß C
>> kein sauberes Modulkonzept kennt und deshalb nicht unterscheiden kann,
>> ob ein Stück Code den exclusiven Zugriff auf eine Variable hat oder
>> nicht.
>
> Absolut nicht.

Absolut doch.

Hab das soeben noch einmal erklärt, siehe dieser Beitrag. Es gibt 
keinerlei sonstigen Grund für 'volatile'. Auch nicht in irgend einem 
Standard: der Grund für die Notwendigkeit von volatile in C ist nicht, 
daß es im Standard steht, sondern daß man dem Compiler etwas ansagen 
muß, was er aufgrund eines Mangels in der Sprachdefinition von selbst 
nicht wissen kann. So herum.

So, Leute - im Grunde ärgert es mich nicht, daß ihr so tief mit der Nase 
in der C-Furche steckt, sondern es ist bedauerlich, daß ihr es nicht für 
nötig haltet, die Nase mal zu erheben und über den Rand der Furche zu 
schauen.

W.S.

von W.S. (Gast)


Lesenswert?

ohne Account schrieb:
> Rolf M. schrieb:
>> weak gibt es in C gar nicht
>
> guter Aspekt; kenne ich nämlich auch nicht ... aber vielleicht haben sie
> es ja im neuesten Standard dazu gekittert.

und:

ohne Account schrieb:
> Weak symbols are not mentioned by the C or C++ language standards; as
> such, inserting them into code is not very portable.
>
> So gewöhnt man sich schlechten Programmierstil an ;-)

Gröhl... Wer es nicht begreift, daß 'weak' eine zwingend einzuführende 
Sache ist, die ganz speziell für das Programmieren von 
Cortex-Architekturen erforderlich ist, der hat die letzten 10 Jahre 
geschlafen.

Es ist eben kein schlechter Programmierstil, sondern eine 
Notwendigkeit, die allerdings auf Assembler-Ebene hätte bleiben können, 
wenn es nicht fanatische C-Anhänger gegeben hätte, die die Forderung 
aufgestellt hatten, daß sie selbst den Startup-Code ebenfalls in C 
formuliert haben wollen. Man hätte das abschlägig beantworten können und 
dann wäre weak niemals irgendwo in C aufgetaucht. Ist aber so nicht 
gelaufen.

Selbstverständlich ist 'weak' überhaupt nicht als portable vorgesehen. 
Das ist ebenso plattformspeziell wie die Adressierung per CS:IP beim 
8086. Warum weiß man hier - in einem dedizierten MIKROCONTOLLER Forum 
- so etwas nicht?

W.S.

von mh (Gast)


Lesenswert?

W.S. schrieb:
> In C kann man im Prinzip jede irgendwo vorkommende Variable mit 'extern
> typ name' oder schlichtweg über das Einbinden der .h (sofern dort diese
> Variable erwähnt ist) erreichen.
Das ist falsch.

W.S. schrieb:
> Hätte man in C ein Modulkonzept, was wie in Pascal ganz klar festlegt,
> was irgend eine andere Instanz überhaupt sehen kann und was nicht, dann
> bräuchte man sowas wie 'volatile' überhaupt nicht. Grund: der Compiler
> könnte selbst feststellen, ob in der Zwischenzeit, wo der gerade
> aktuelle Code läuft, von woanders ein Zugriff überhaupt möglich ist oder
> nicht.
Und mit diesem Modulkonzept weiß der Compiler dann, wann sich ein 
Hardwareregister ändert? Verkaufst du mir so ein Modul? Dann kann ich 
meine Kristallkugel entsorgen...


Bist du dir sicher, dass du const in C verstanden hast? Wie genau 
erklärst du
1
#include <stdlib.h>
2
int main() {
3
    int const foo = rand();
4
    return foo;
5
}
Wird die Zufallszahl zur Laufzeit in den Flash/schreibgeschützten RAM 
geschrieben?


W.S. schrieb:
> Gröhl... Wer es nicht begreift, daß 'weak' eine zwingend einzuführende
> Sache ist, die ganz speziell für das Programmieren von
> Cortex-Architekturen erforderlich ist, der hat die letzten 10 Jahre
> geschlafen.
Kannst du etwas genauer erklären, warum man für Cortex unbedingt week 
braucht? Und warum man wegen dieser einen Architektur weak im C-Standard 
einführen muss?

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Im Grunde könnte der Compiler für jeden Lesezugriff auf eine Variable
> eben auf diese zugreifen. Macht er aber aus Optimierungsgründen oftmals
> nicht.

So weit noch richtig.

> Jedoch kann ein C-Compiler bei globalen Variablen oder gar
> Hardware-Registern eben nicht feststellen, ob sich der Inhalt eben
> dieser Variable aus Gründen ändern kann, die außerhalb des
> Sichtbereiches der vorliegenden Quelle stehen.

Und das stimmt eben so nicht. Wie schon oben geschrieben, geht es nicht 
um alle Änderungen außerhalb des Sichtbereichs des Quellcodes, sondern 
um welche außerhalb des normalen Programmflusses. Also sobald 
Nebenhäufigkeiten durch Threads, Interrupts oder gleichzeitige Zugriffe 
durch externe Hardware vorkommen. Genau dann braucht man volatile, und 
genau dafür ist es auch gemacht. Ob dies nun innerhalb eines Moduls oder 
über mehrere Module hinweg passiert, ist dafür komplett unerheblich.

> Hätte man in C ein Modulkonzept, was wie in Pascal ganz klar festlegt,
> was irgend eine andere Instanz überhaupt sehen kann und was nicht, dann
> bräuchte man sowas wie 'volatile' überhaupt nicht.

Und wie sorgt dein Pascal-Modulkonzept dafür, dass der Compiler bei 
einer Schleife wie:
1
while (true)
2
{
3
   if (interrupt_flag)
4
   {
5
        led_pin = !led_pin;
6
        interrupt_flag = false;
7
   }
8
}
weiß, dass interrupt_flag plötzlich irgendwann mitten drin durch eine 
ISR verändert werden kann? Und wie sorgt es dafür, dass für die Variable 
led_pin, die in diesem Fall ein Hardware-Register ist, auch auf jeden 
Fall immer ein vollständiger Schreibzugriff erfolgt, damit die LED auch 
tatsächlich toggelt?

> In C kann man im Prinzip jede irgendwo vorkommende Variable mit 'extern
> typ name' oder schlichtweg über das Einbinden der .h (sofern dort diese
> Variable erwähnt ist) erreichen.

Ja, aber das hat erst mal nichts, aber überhaupt nichts, mit volatile zu 
tun.

> Damit ist der Compiler ausgehebelt, er kann nicht feststellen, ob die
> Variable von woanders her erreichbar ist oder nicht.

So lange ich (ohne Nebenläufigkeiten) keinen externen Code aufrufe, kann 
dieser auch nicht auf die Variable zugreifen, da er gar nicht zur 
Ausführung kommt. Deshalb braucht man dafür auch kein volatile. Mit 
Nebenläufigkeiten braucht man volatile, allerdings ist das nicht 
abhängig davon, ob der Code "woanders" steht oder nicht. Für das obige 
ISR-Flag ist volatile nötig, sowohl wenn der Code in der selben C-Datei 
steht, als auch, wenn er in einer anderen steht. Der Compiler weiß 
nämlich nicht, dass die ISR nicht wie eine normale Funktion aufgerufen 
werden muss, damit sie ausgeführt wird, sondern vielmehr durch externe 
Hardware getriggert den Programmfluss plötzlich mittendrin unterbricht, 
ohne dass dort je irgendwo ein Aufruf stehen würde.

> 2. und warum benötigt const eine Wertfestlegung? Ist dir der tiefere
> Grund dafür bewußt?

Der ist doch ziemlich trivial. Wie soll da sonst je ein sinnvoller Wert 
rein kommen, wenn nicht bei der Initialisierung? Mit const sichere ich 
zu, dass ich später den Wert nicht mehr ändern werde. Es gibt also nur 
eine einzige Stelle, wo man sie mit einem Wert belegen kann.

> 3. Der Grund ist, daß diese 3.1415 eben nicht in irgendwelche
> Maschinenbefehle eingebaut wird, sondern tatsächlich eine Variable ist,
> die jedoch im CODE steht.

Nein. Wo die steht, ist immer noch Implementierungsdetail. C macht da 
keinerlei Vorgaben dazu.

> Im Mikrocontroller also im Flash, am PC je nach OS in einem
> schreibgeschützten (oder nicht schreibgeschützten) Stück RAM (wäre vom
> Prinzip her dasselbe wie Flash: R/O und nicht R/W).

Kann der Compiler so implementieren, muss er aber nicht. Und ist auch 
oft nicht. Das hat auch erst mal nichts damit zu tun, ob es um einen PC 
oder einen µC geht. Eine solche Unterscheidung kennt C gar nicht.
Ein Gegenbeispiel gibt es auch: AVR. Eine extern-Variable, die einfach 
als const definiert ist, landet dort im RAM.

> Das ist etwas anderes als das Vereinbaren einer Variablen, für die man
> ja nur Platz reservieren muß. Hast du das jetzt begriffen?

Es ist nichts anderes.

>> Deine Erklärung ist einfach falsch. "const" sagt dem Compiler, dass der
>> Wert dieser Variablen vom Programm nicht geändert werden darf.
>
> Siehe oben, du liegst falsch. Der Hauptgrund ist, daß diese Variable ein
> Teil des zu erzeugenden Codes wird und nicht, daß der Compiler weiß, daß
> man sie nicht beschreiben darf. Das ist ne Schlußfolgerung, die zwar
> logisch, am PC jedoch oftmal völlig falsch ist.

Es ist exakt umgekehrt.

> Erinnere dich mal an die Zeiten von DOS: dort konnte man const vereinbaren
> und dennoch drauf herumschreiben. Ja, das ging.

Klar, wobei dabei nach C schon immer undefiniertes Verhalten rauskam. 
Und in der Praxis hat es auch nicht immer funktioniert, je nach 
Optimierungsverhalten des Compilers. Denn er darf ja auf Grund meiner 
Zusicherung "const" annehmen, dass sich der Inhalt niemals ändert und 
das entsprechend bei seinen Optimierungen berücksichtigen.

> Also begreife mal:
> const ist dafür, daß etwas in den Code kommt - und zwar nicht implizit
> in den Maschinenbefehlen, sondern explizit als typisierte und mit Wert
> versehene Variable.

Kann beides sein, kann auch was anderes sein. Das bleibt komplett dem 
Compiler überlassen, und es gibt in der Praxis alle Varianten. Wie du 
das als Beleg für deine dem entgegenstehende Theorie sehen kannst, 
erschließt sich mir beim besten Willen nicht.

> volatile ist dafür, daß man dem Compiler ansagt, daß die Variable auch
> von anderen Instanzen geändert werden kann

Der wichtige Teil, der hier wieder fehlt: gleichzeitig! Wenn ich eine 
Funktion ganz einfach aufrufe, sie eine Variable verändert und dann 
wieder zurückkehrt, ist volatile selbstverständlich vollkommen 
überflüssig, egal ob diese Funktion oder die Variable in der selben oder 
einer anderen C-Datei definiert ist.

> Hab das soeben noch einmal erklärt, siehe dieser Beitrag. Es gibt
> keinerlei sonstigen Grund für 'volatile'.

Oh mann… es gibt ausschließlich "sonstige Gründe", weil der von dir 
angebrachte Grund einfach Unsinn ist.

> Auch nicht in irgend einem Standard: der Grund für die Notwendigkeit von
> volatile in C ist nicht, daß es im Standard steht, sondern daß man dem
> Compiler etwas ansagen muß, was er aufgrund eines Mangels in der
> Sprachdefinition von selbst nicht wissen kann. So herum.

Auch nicht. Das volatile ist gerade das, was dafür sorgt, dass es diesen 
Mangel in der Sprachdefinition nicht gibt.

> So, Leute - im Grunde ärgert es mich nicht, daß ihr so tief mit der Nase
> in der C-Furche steckt, sondern es ist bedauerlich, daß ihr es nicht für
> nötig haltet, die Nase mal zu erheben und über den Rand der Furche zu
> schauen.

Mich ärgert es allerdings, dass du so daneben liegst und da so 
hartnäckig daran festhältst, ohne mal darüber zu reflektieren, ob es 
nicht vielleicht doch eben du bist, der hier falsch liegt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> Frank M. schrieb:
>> Deine Erklärung ist einfach falsch. "const" sagt dem Compiler, dass der
>> Wert dieser Variablen vom Programm nicht geändert werden darf.
>
> Siehe oben, du liegst falsch.

Tut mir leid, ich habe an dieser Stelle keine Lust mehr, mit jemandem zu 
diskutieren, der überhaupt keine Ahnung hat, dies aber vehement vorgibt. 
Ich bleibe bei meiner Aussage.

Lerne erstmal C, bevor Du weiter mit solchen Behauptungen kommst. Wenn 
Du es tatsächlich geschafft hast, unter DOS in C eine const-Variable 
tatsächlich zu ändern, war der verwendete Compiler schlichtweg 
fehlerhaft. Das Schlüsselwort "const" gibt es für C seit 1984 (C++: 
1983).

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
>> volatile ist dafür, daß man dem Compiler ansagt, daß die Variable auch
>> von anderen Instanzen geändert werden kann
>
> Der wichtige Teil, der hier wieder fehlt: gleichzeitig!

Gleichzeitig ist da wohl der falsche Begriff. volatile sagt dem 
Compiler, daß sich die Variable JEDERZEIT durch Vorgänge, die völlig 
ausserhalb seines Vorstellungsvermögens (sprich : Ausserhalb des Scopes 
der Sprachdefinition) liegen, ändern kann.

Oliver

von Oliver S. (oliverso)


Lesenswert?

W.S. schrieb:
> Nö. Eigentlich ist das eben nicht der Sinn des Ganzen, sondern der Sinn
> (und die Anwendung) ist, daß eben diese "Variable" nicht im RAM
> angeordnet sein soll, sondern im Flash.

Zitat aus dem Standard (hier C++17 draft, aber egal):
1
134)The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the
2
implementation need not allocate storage for such an object if its address is never used.

Die Anordnung im "Flash" ist unverbindlich und implementationsabhängig, 
und eine Existenz im Speicher überhaupt ist explizit nur dann gefordert, 
wenn es unvermeidlich ist. Das kann daher gar nicht der Sinn des Ganzen 
sein.

Oliver

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bitte nicht den ganzen Thread nochmal aufrollen. Letztlich wurde W.S. da 
oben inhaltlich schon (mehrfach) widerlegt.

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


Lesenswert?

Frank M. schrieb:
> Tut mir leid, ich habe an dieser Stelle keine Lust mehr, mit jemandem zu
> diskutieren, der überhaupt keine Ahnung hat, dies aber vehement vorgibt.
> Ich bleibe bei meiner Aussage.

Das ist dein Problem.

Und ich bleibe bei meiner Aussage: const ist dafür da, eine KONSTANTE 
und zwar eine typisierte Konstante zu erzeugen. Alles andere ist 
nebensächlich, einschließlich Jörgs Herumhacken auf irgendwelchen 
Standards. manchmal kommt mir Jörg vor wie Herr Palmström:
https://www.oppisworld.de/morgen/palm09.html
Anstatt den digitalen Tatsachen ins Auge zu sehen, blickt er lieber in 
den Standard - und was da nicht steht, das gibt es auch nicht.

Uff.

So, jetzt weißt du wieder nicht, was eine typisierte Konstante ist. Ich 
hab das ja weiter oben schon gesehen, hielt deinen dummen Spruch jedoch 
für einen Scherz. Nun sehe ich, daß du das ernst meinst.

Also schaue dir mal das an:
1
in Pascal:
2
var
3
  SimplePi = 3.1415;
4
  TypisisertPi : double = 3.1415;
5
6
oder in C:
7
#define SimplePi  3.1415
8
const double TypisisertPi = 3.1415;

Erkennst du an diesem Beispiel den gravierenden Unterschied zwischen 
SimplePi und TypisiertPi ?

SimplePi wird bei Bedarf lediglich in irgendwelchen Maschinenbefehlen 
verwendet, aber TypisiertPi erzeugt Code, also etwas, das nicht nur 
Platz belegt, sondern auch mit einem Inhalt daherkommt und folglich 
beim PC in die .EXE und damit auf die Disk kommt und am µC eben in den 
Flash (wie ich bereits sagte).

Und letzteres gilt auch dann, wenn TypisiertPi beim Programmstart in den 
RAM kopiert wird. Aus der Luft kommt es ja nicht, also muß es im 
gespeicherten Code vorhanden sein.

Kapierst du das Ganze jetzt endlich?

W.S.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

W.S. schrieb:
> einschließlich Jörgs Herumhacken auf irgendwelchen Standards

Definierst du dir eigentlich auch deine eigenen Schrauben, oder hälst du 
dich dort doch lieber an Standards?

Kann ja sein, dass du dir deine eigene Programmiersprache definierst, 
aber es wäre dann fair gegenüber den anderen Forennutzern, wenn du 
dieser zumindest einen anderen Namen geben würdest, "WS" vielleicht - 
damit die anderen das nicht mit einer einigermaßen populären und 
standardisierten Sprache verwechseln, was du da so definierst.

Sorry, mehr kann man dazu leider nicht sagen. Vernünftige Begriffe, auf 
die sich alle anderen geeinigt haben, willst du ja schließlich nicht 
verwenden.

von mh (Gast)


Lesenswert?

W.S. schrieb:
> SimplePi wird bei Bedarf lediglich in irgendwelchen Maschinenbefehlen
> verwendet, aber TypisiertPi erzeugt Code, also etwas, das nicht nur
> Platz belegt, sondern auch mit einem Inhalt daherkommt und folglich
> beim PC in die .EXE und damit auf die Disk kommt und am µC eben in den
> Flash (wie ich bereits sagte).

Kannst du kein Englisch, oder warum verstehst du den, von Oliver S. 
zietierten, Ausschnitt aus dem Standard nicht? Oder verstehe ich nicht 
was du mit "erzeugt Code" und "belegt Platz" ausdrücken willst?

: Wiederhergestellt durch Moderator
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Ich will in einer .c-Datei ein "Default" einer
> (struct)-Konfigurationsvariablen anlegen, die aber in einer anderen
> Datei überschreiben können.

Das ist nur sinnvoll, wenn is unterschiedliche Generieungsvarianten 
gibt, und die werden üblicherweise über die Generierungsumgebung 
verwaltet, z.B. über ein Makefile.  Und genau dort kannst du 
unterschiedliche Generierungsvarianten vor Belegung "A" oder "B" 
festlegen.

Resultat wären etwa:

* Unterschiedliche Präprozessor-Defines je nach Variante, also gcc -D...

* Unterschiedliche Module mit der Vorbelegung wie module-A.c und 
module-B.c, wobei nur genau eines der Module wirklich gelinkt wird.

von Oliver S. (oliverso)


Lesenswert?

W.S. schrieb:
> Und ich bleibe bei meiner Aussage: const ist dafür da, eine KONSTANTE
> und zwar eine typisierte Konstante zu erzeugen. Alles andere ist
> nebensächlich

Das ist auf Quelltextebene richtig, mit allen Vorteilen einer 
typischeren Programmierung gegenüber einer define-Konstanten. Im 
kompilierten Programmcode landet die const-Variable aber nur, wenn der 
Compiler die nicht wegoptimieren kann. Meistens kann und tut er das 
aber.

Oliver

: Bearbeitet durch User
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

W.S. schrieb:
> Kapierst du das Ganze jetzt endlich?

Du hast mal wieder nix kapiert!
Der Verleich mit dem precompiler und einer const ist ja echt mal wieder 
hanebüchen.
Sowas kann nur von dir kommen.
Nur mal so als tip:
ARM z.B. legt lokales direkt hinter den Codeblock.
Das wäre jetzt dein "erzeugt Code" und "belegt Platz".
Das const double kommt übrigens nicht ind en Flash bei ARM, der Compiler 
is mal wieder schlauer als du ;)
1
void ws_kann_mal_wieder_nix(void) {
2
  printf("thats pi: %f", SimplePi);
3
}
SimplePi ist einmal const und einmal das define.
Dann jeweils mal copiled und:
Bei beiden kommt übrigens raus:
1
08000cfc <_Z22ws_kann_mal_wieder_nixv>:
2
 8000cfc:  b510        push  {r4, lr}
3
 8000cfe:  4a03        ldr  r2, [pc, #12]  ; (8000d0c <_Z22ws_kann_mal_wieder_nixv+0x10>)
4
 8000d00:  4b03        ldr  r3, [pc, #12]  ; (8000d10 <_Z22ws_kann_mal_wieder_nixv+0x14>)
5
 8000d02:  4804        ldr  r0, [pc, #16]  ; (8000d14 <_Z22ws_kann_mal_wieder_nixv+0x18>)
6
 8000d04:  f003 fa24   bl  8004150 <iprintf>
7
 8000d08:  bd10        pop  {r4, pc}
8
 8000d0a:  46c0        nop      ; (mov r8, r8)
9
 8000d0c:  c083126f   addgt  r1, r3, pc, ror #4
10
 8000d10:  400921ca   andmi  r2, r9, sl, asr #3
11
 8000d14:  08005148   stmdaeq  r0, {r3, r6, r8, ip, lr}
Die "komisch" disassemblierten Befehle ab 8000d0c sind übrigens die 
lokalen Konstanten ;)

DU solltest eben einfach mal leise sein wenn sich die Erwachsenen 
unterhalten!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mw E. schrieb:
> DU solltest eben einfach mal leise sein wenn sich die Erwachsenen
> unterhalten!

Bitte nicht auf diesem Niveau.

W.S. ist streitbar (und natürlich sind alle anderen die Geisterfahrer, 
nur er nicht), aber diese Tonart brauchen wir nicht im Forum.

von Rolf M. (rmagnus)


Lesenswert?

Jörg W. schrieb:
> Mw E. schrieb:
>> DU solltest eben einfach mal leise sein wenn sich die Erwachsenen
>> unterhalten!
>
> Bitte nicht auf diesem Niveau.

Das ist halt das Niveau von W.S., an das sich die anderen hier anpassen:

W.S. schrieb:
> Soviel Nicht-Denken-Wollen ärgert mich.
>
> Also für die Langsamdenker mal im Einzelnen:

W.S. schrieb:
> Gröhl... Wer es nicht begreift,

W.S. schrieb:
> hielt deinen dummen Spruch jedoch für einen Scherz

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Das ist halt das Niveau von W.S., an das sich die anderen hier anpassen:

Stimmt auch wieder.

Da in diesem Thread sowieso alles gesagt worden ist, was zum Thema 
gehört, würde ich Rolfs Worte einfach mal als Abschlussworte so stehen 
lassen.

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.