Forum: Mikrocontroller und Digitale Elektronik verhalten von defines in C


von Chandler B. (chandler)


Lesenswert?

Hallo,
ich habe eine Verständinsfrage zu defines in C.
1
#define TYPE               "ABC"
2
#define VARIATION          "_2"
3
#define MAJOR_VERSION      "00"
4
#define MINOR_VERSION      "900"
5
#define SUB_REVISION       "00"
6
7
#define VERSION_STRING TYPE "." VARIATION "." MAJOR_VERSION "." MINOR_VERSION "." SUB_REVISION
8
9
10
... ... ...
11
... ... ...
12
13
char version = VERSION_STRING;
14
15
... ... ...

Ich habe jetzt zwei Verschieden Möglichkeiten gehört. Und bin mir nicht 
sicher was jetzt richtig ist.
1) Wird das define beim Compilieren direkt ersetzen?
Also steht dann dort quasi
1
char version = "ABC._2.00.900.00"
oder
2) steht das Define irgendwo im Speicher? Und version zeigt darauf?

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Ich tendiere stark zu deiner Moeglichkeit 1 und erhoehe um Probleme, die 
du kriegst, weil in einen char nur ein Zeichen passt und kein ganzer 
String.

Gruss
WK

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Chandler B. schrieb:
> 1) Wird das define beim Compilieren direkt ersetzen?

Der Präprozessor löst die Defines und Includes auf.
Danach kommt der Compiler dran.

Chandler B. schrieb:
> 2) steht das Define irgendwo im Speicher?
Nicht das Define, aber der String wird sich in irgendeinem Speicher 
befinden.

von Chandler B. (chandler)


Lesenswert?

Dergute W. schrieb:
> und erhoehe um Probleme, die
> du kriegst, weil in einen char nur ein Zeichen passt und kein ganzer
> String.

Das ist richtig.
Sollte
1
char version[20] = VERSION_STRING;

Arduino F. schrieb:
> Nicht das Define, aber der String wird sich in irgendeinem Speicher
> befinden.
Der String an für sich? Oder der String in der Variablen version?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Chandler B. schrieb:
> Der String an für sich?
Natürlich!

Chandler B. schrieb:
> Oder der String in der Variablen version?
Verstehe ich nicht.

von Helmut -. (dc3yc)


Lesenswert?

Aber ein #define ersetzt nur die eine Zeichenkette durch die andere. 
Deinen String wirst du dir schon noch selber zusammenbauen müssen!

von Udo S. (urschmitt)


Lesenswert?

schaue dir an was vom Preprozessor raus kommt.
Je nach Compiler suche nach "Preprocessor output to file"
Siehe z.B.
https://stackoverflow.com/questions/8978997/how-can-i-see-the-output-of-the-visual-c-preprocessor

von Nick (b620ys)


Lesenswert?

Chandler B. schrieb:
> 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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Chandler B. schrieb:
> Ich habe jetzt zwei Verschieden Möglichkeiten gehört.
Nicht glauben!
Lernen!

https://en.cppreference.com/w/c/preprocessor.html

von Obelix X. (obelix)


Lesenswert?

Chandler B. schrieb:
> Wird das define beim Compilieren direkt ersetzen?
> Also steht dann dort quasi

Es Wird ersetzt durch

char version = "ABC" "." "_2" "." "00" "." "900" "." "00";

von Nikolaus S. (Firma: Golden Delicious Computers) (hns)


Lesenswert?

Der C-Präprozessor ersetzt in einer ersten Runde:
1
char version[20] = VERSION_STRING;
durch
1
char version[20] = TYPE "." VARIATION "." MAJOR_VERSION "." MINOR_VERSION "." SUB_REVISION;
und in einer zweiten durch
1
char version[20] = "ABC" "." "_2" "." "00" "." "900" "." "00";
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.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

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
char version[] = "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.

C++:  "A" R"X(B)X"  entspricht  "AB"
python: "test" 'abc' f"{123}"  entspricht  "testabc123"
bash: "A"'B'C  entspricht  "ABC"

: Bearbeitet durch User
von Rbx (rcx)


Lesenswert?

Chandler B. schrieb:
> Wird das define beim Compilieren direkt ersetzen?

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.

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


Lesenswert?

Nick schrieb:
> Die Variable verweist darauf.

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.

: Bearbeitet durch Moderator
von Nick (b620ys)


Lesenswert?

Jörg W. schrieb:
> 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. ;-)

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Nick schrieb:
> 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

: Bearbeitet durch User
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.