Der String an für sich? Oder der String in der Variablen version?
Der String steht irgendwo im Speicher. Die Variable verweist darauf.
#defines die nicht verwendet werden, werden einfach ignoriert, weil sie ... nicht verwendet werden.
Das wird dann an den eigentlichen C-Compiler weitergegeben.
Der weiss dass zwei hintereinander stehende Strings zusammengesetzt werden sollen. Also ist das identisch zu:
1
char version[20] = "ABC._2.00.900.00";
Das versteht der Compiler nun so, dass er im Speicher 20 Bytes reserviert und mit den Zeichen ABC._2.00.900.00 vorbelegt.
Also gehört der String zum Programmspeicher und steht dann bei der Ausführung im Speicher. Und "version" verweist auf die Speicheradresse, so dass z.B. version[5] eine '2' ergibt.
Die defines werden einfach ersetzt durch das, als was sie definiert wurden.
Jag es einfach mal durch den Präprozessor, dann siehst du, daraus wird: https://godbolt.org/z/GYErcPzGP
1
charversion[]="ABC"".""_2"".""00"".""900"".""00";
Mehrere String literale nacheinander werden dann vom Compiler wie ein einzelnes behandelt. Ist recht praktisch, haben diverse andere Sprachen auch so übernommen, und dort gibt es oft mehrere Arten String-literale zu schreiben.
Nein, der Code wird zuerst beispielsweise wie mit der Suchfunktion im VI-Editor angepasst. Auf diese Weise kann man Makro-Szenarien erstellen, welche die Programmierung erleichtern, (oder ihn besser Dokumentieren, LOL) oder Konstanten wie Mathematische Fix-Zahlen (wie PI) einfliegen.
Zu Anfangszeiten von C meinten auch einige, mit Hilfe dieser Vorkau-Steuerung C wieder zurück nach Assembler zu frisieren. In Assembler sind ja auch Makros nicht standardisiert, wo man sich dann über Dialekte wundern kann.
Nicht ganz. So, wie es da steht, ist es ja echt eine Variable, also etwas, was zur Laufzeit geändert werden kann.
Damit steht der String irgendwo (read-only) im Speicher. Beim Start des Programms wird er von da in die Variable kopiert, steht also alles in allem dann zweimal im Speicher.
Aber das hat natürlich jetzt nichts (mehr) mit dem preprocessing zu tun.
Der Präprozessor war früher oft ein eigenes Programm, heute ist er es meist nicht mehr. Spielt aber für seine Funktionsweise jetzt keine Rolle.
Damit steht der String irgendwo (read-only) im Speicher. Beim Start des
Programms wird er von da in die Variable kopiert, steht also alles in
allem dann zweimal im Speicher.
Ja, gut. OK!
Hätte er halt const char[] schreiben sollen. ;-)
Es ist implementation Defined, wo der String dann landet.
z.B. bei den alten AVR wird er trotz const ins RAM kopiert.
Da aufgeteile Adressierung RAM vs Flash vs EEPROM
s ist implementation Defined, wo der String dann landet.
OK, mag so sein.
Ich könnte aber auch argumentieren, dass der Compiler merkt, dass der Versionsstring nie verändert wird und daher im ROM steht. Das ist sicherlich auch Compilerabhängig.
Wenn du (wie beim klassischen AVR) für den Zugriff auf den ROM andere Befehle als für den Zugriff auf den RAM brauchst, musst du u.U. Dinge im RAM ablegen, damit hernach sowas wie strcpy() funktioniert.
Aber dann musst du es auf dem AVR auch richtig machen.
Die Frage war aber nicht spezifisch für den AVR. Also interessiert hier nur der Standard.
Die Sonderlocke __flash mag zwar für den AVR richtig sein, aber hier argumentativ nicht relevant.
Die Diagnostic (Warning / Error), dass einem char ein const char* zugewiesen wird, wird in Translation Phase 7 ausgegeben: The resulting tokens are syntactically and semantically analyzed and translated as a translation unit.
Hier ist "version" einfach nur ein prt auf einen (const) text.
version selbst ist auch konstant, kann also nicht einfach auf einen anderen Text umgelegt werden.
Und egal ob im Ram oder Rom, normalerweise ist das die Darstellung mit der geringsten Wahrscheinlichkeit von doppeltem Speicher oder späterer Änderung.
(Das hat aber alles nichts mehr mit VERSION_STRING oder Präprozessor zu tun, das wurde zu Anfang gut erläutert)
Mit "const" könnte man dem Compiler natürlich zumindest auf den Plattformen, wo es problemlos möglich ist, einen Hinweis geben, dass er den String nur einmal ablegen muss.
Da sind wir uns also einig. Irgendwelche Ausnahmen oder Plattformspezifika wurden vom TO nicht gefragt.
Ich find die Frage des TO auch in keiner Weise dumm. Er hat halt Wissenslücken (hatte jeder mal) und hat in einer klaren Art & Weise gefragt. Er hat auch gute Antworten dafür bekommen. Nur gibts halt paar Leute die entweder nicht ordentlich lesen können, oder sich mit ihrem Nischenwissen hervortun müssen.
Mit dir kann man ja auch auf einer vernünftigen Ebene argumentieren.