Forum: Compiler & IDEs #define als String "umdefinieren"


von Dirk (Gast)


Lesenswert?

Hallo!

Ich würde gerne wissen, ob es eine Möglichkeit gibt, ein define auf zwei 
Arten zu benutzen:

#define ZAHL 123

Das brauche ich irgendwo im Code in folgender Form:

int n = ZAHL;
bla...

Aber ich möchte auch einen String (im ROM) damit initialisiert haben:

char ROMCONST asN[3] = "123";

So funktioniert´s nicht, klar:

char ROMCONST asN[3] = "ZAHL";

Wie mach ich dem Compiler klar, daß er für ZAHL in den Hochkommas "123" 
(als String!) einsetzen soll?
Gibt´s da ne Möglichkeit?

Gruß, Dirk.

von Karl H. (kbuchegg)


Lesenswert?

Dirk wrote:
> Gibt´s da ne Möglichkeit?

Ja gibt es.
Du brauchst dazu das 'Stringize' #-Token des Präprozessors.
1
#define STR(x)   #x
2
#define XSTR(x)  STR(x)
3
4
#define TEST   17
5
6
int main()
7
{
8
  printf( "%s", XSTR(TEST) );
9
}

Der Umweg über ein Zwischenmakro ist notwendig, damit die
Makroauswertung korrekt abläuft.

von Johannes M. (johnny-m)


Lesenswert?

Verstehe noch nicht ganz, was Du wirklich willst, aber von den beiden 
Varianten...
> char ROMCONST asN[3] = "123";
>
> So funktioniert´s nicht, klar:
>
> char ROMCONST asN[3] = "ZAHL";
funktioniert keine . "123" sind in C 4 Zeichen, und die passen nicht 
in ein Array mit 3 Elementen rein, von "ZAHL" (5 Zeichen) mal ganz zu 
schweigen. Meist ist es überflüssig, bei einem Array, das explizit 
initialisiert wird, die Breite anzugeben.

Aber wenn ich das korrekt verstehe, dann macht die erste Variante (wenn 
Du die 3 in den eckigen Klammern weglässt) genau das, was Du willst. 
Nach
1
char asN[] = "123";
steht in asN[0] eine '1' (0x31), in asN[1] eine '2' (0x32), in asN[2] 
eine '3' (0x33) und in asN[3] eine '\0' (0x00).

EDIT:
Oder wolltest Du doch was anderes? Wenn ja, dann liegt Karl Heinz 
möglicherweise richtig...

NOCH EIN EDIT:
Ich glaub, so langsam fällt der Groschen... Aber wie gesagt und 
unabhängig davon: Achte auf den Nullterminator!

von Dirk (Gast)


Lesenswert?

Vielen Dank euch beiden.

Genau das, was Karl Heinz erläutert hat, hab ich gesucht...
Ich hab den Operator zwar schon gefunden gehabt 
(http://www.tfh-berlin.de/~kempfer/skript_c/Kap12.html), aber ich bin 
natürlich nicht auf die Idee gekommen, das nochmal zu "makrofizieren" ;)

@Johannes: Ja, sorry, das hätte ich sagen sollen: Die Nullterminierung 
will/brauch ich eben nicht, weil ich noch eine zweite Konstante habe, 
die den Platz im Array entsprechend reserviert (wird noch anderswo für 
ein Objekt-Verzeichnis benötigt, deswegen kann ich das Array nicht 
einfach "so" initialisieren...)


Gruß, Dirk.

von Johannes M. (johnny-m)


Lesenswert?

Dirk wrote:
> @Johannes: Ja, sorry, das hätte ich sagen sollen: Die Nullterminierung
> will/brauch ich eben nicht, weil ich noch eine zweite Konstante habe,
> die den Platz im Array entsprechend reserviert (wird noch anderswo für
> ein Objekt-Verzeichnis benötigt, deswegen kann ich das Array nicht
> einfach "so" initialisieren...)
Ob Du die brauchst oder nicht, denk daran, dass ein Ausdruck in "" immer 
nullterminiert ist, und dass der Ausdruck auch in den Speicher 
geschrieben wird, ohne Rücksicht auf Verluste. Wenn hinter dem letzten 
'reservierten' Array-Element schon was anderes steht, dann Peng ...

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


Lesenswert?

Johannes M. wrote:

> Ob Du die brauchst oder nicht, denk daran, dass ein Ausdruck in "" immer
> nullterminiert ist,

Jein.

> und dass der Ausdruck auch in den Speicher
> geschrieben wird, ohne Rücksicht auf Verluste.

Nein.

6.7.8 Initialization, Absatz 14:

“An array of character type may be initialized by a character string
literal, optionally enclosed in braces. Successive characters of the
character string literal (including the terminating null character if
there is room or if the array is of unknown size) initialize the
elements of the array.”

Man beachte das “if there is room”.

von Johannes M. (johnny-m)


Lesenswert?

Jörg Wunsch wrote:
> 6.7.8 Initialization, Absatz 14:
>
> “An array of character type may be initialized by a character string
> literal, optionally enclosed in braces. Successive characters of the
> character string literal (including the terminating null character if
> there is room or if the array is of unknown size) initialize the
> elements of the array.”
>
> Man beachte das “if there is room”.
Hmmm, bei der Initialisierung kann also tatsächlich nix kollidieren? 
Bedeutet also, dass, wenn die Array-Größe explizit angegeben wird, diese 
Angabe (zumindest bei einer Initialisierung) das mächtigere Argument 
ist? OK, und bei der Initialisierung besteht auch noch die Möglichkeit, 
sich den Speicher nach Bedarf zurechtzubiegen, da Compiler und Co. ja 
sehen, was da passiert...

Aber gilt das nur für den Nullterminator? Wenn andere Zeichen über die 
Array-Grenzen hinaus geschrieben werden sollen, müsste es ja mindestens 
ne Warnung geben.

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


Lesenswert?

Johannes M. wrote:

> Hmmm, bei der Initialisierung kann also tatsächlich nix kollidieren?

Ja, schließlich hat der Compiler ja eine explizite Anweisung dazu
erhalten, wie groß das Array werden soll.

> Aber gilt das nur für den Nullterminator?

Mehr ist zumindest erstmal vom Standard nicht abgedeckt.

> Wenn andere Zeichen über die
> Array-Grenzen hinaus geschrieben werden sollen, müsste es ja mindestens
> ne Warnung geben.

Würde ich auch erwarten.  Test:
1
% cat foo.c
2
char foo[4] = "Hello";
3
% cc -Os -Wall -Wextra -c foo.c
4
foo.c:1: warning: initializer-string for array of chars is too long

von Johannes M. (johnny-m)


Lesenswert?

@ Jörg Wunsch:
Aha. Danke vielmals. Wieder was gelernt.

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.