# #define für Text ?



## AckiB (20. Mai 2004)

Hallo,
ich habe da ein Problem, dass eigentlich kein Problem sein dürfte...  
Ich habe am Anfang der Datei ein #define für die Stringlänge.
Das funktioniert auch wie erwachtet, bis auf eine Ausnahme:


```
#define MAXSTRING 256

void loadData(){
  char iniFile[MAXSTRING]; // wird wie erwartet erstetzt
  cIniEd tmp;

  strcpy(iniFile, projekt_Daten.projekt_Pfad);
  strcat(iniFile, "MAXSTRING.ini"); // wird nicht erstetzt
  tmp.setPfad(iniFile);

}
```

Ich erhalte immer den Dateinahmen "MAXSTRING.ini", der sollte aber doch jetzt "256.ini" sein, oder ?

CU, Acki


----------



## Kachelator (20. Mai 2004)

Versuch es mal so:

```
#define MAXSTRING "256"
strcat(iniFile, MAXSTRING ".ini"); // wird nicht erstetzt
```
Eine andere Lösung kenne ich nicht, ausser Umwandlungsfunktionen (Z.B. sprintf()) oder Ausgabestreams zu verwenden.
Beispiel:


```
#define MAXSTRING (256)

...

  char buffer[40];
  sprintf( buffer, "%d.ini", MAXSTRING );
  printf( buffer );
  strcat(iniFile, buffer ".ini");
```
Übrigens könntest du die Zeile mit dem #define besser durch folgende ersetzen:

```
const int MAXSTRING = 256;
```


----------



## Gawayn (20. Mai 2004)

@Kachelator: Wieso sollte man ein #define deiner Ansicht nach durch ein const ersetzen? Dieser Grundsatz ist mir völlig neu!

Gawayn


----------



## Kachelator (20. Mai 2004)

Nach Möglichkeit  sollte man auf Defines ganz verzichten, wenn man stattdessen typsichere Definitionen verwenden kann. Im Unterschied zu #Defines, die im Quelltext ersetzt  werden, bevor der Compiler sie zu Gesicht bekommt, geht beispielsweise das "const int " so an den Compiler weitergegeben. Das kann sehr hilfreich bei der Fehlervermeidung sein. Ebenso halte ich es für sinnvoll, wo es geht, Funktionstemplates anstelle von Define-Makros zu verwenden. Das setzt natürlich C++ voraus.

Eine beliebte Falle stellt zum Beispiel das Makro max() aus der windef.h dar:

```
#define max(a,b)            (((a) > (b)) ? (a) : (b))
```
Das Problem ist, das a und b je nach ihrem  Wert hier ein oder zwei mal ausgewertet werden, ohne dass das im Code offensichtlich wäre. Was passiert nämlich, wenn a zum Beispiel ein Ausdruck der Form ++i ist...?
Ich glaube, zu der Thematik findet man im Netz reichlich Material. Hier zum Beispiel:


> Makros:
> Makros sind in C sehr wichtig.
> #define SQUARE(a) a*a
> int x = 5;
> ...


 (Quelle: http://www.wackerart.de/c.html )


----------



## Gawayn (20. Mai 2004)

Ja, dieser Problematik bin ich mir bewusst. Ich setze Defines ausschließlich für Konstante ein. Auf solche Scherze wie max( ++a, b ) verzichte ich ohnehin -- ich denke, wer soetwas schreibt, schreit nach Fehlern. Mitdenken ist angesagt. Defines haben halt den großen Vorteil, effizienteren Code zu erzeugen, da ja ein ganzer Speicherzugriff entfällt. Die Zahl, auf die es ankommt, ist bereits im Mnemonic kodiert und muss nicht noch von einer anderen Adresse geladen werden.

Gawayn


----------



## Kachelator (20. Mai 2004)

> Mitdenken ist angesagt. Defines haben halt den großen Vorteil, effizienteren Code zu erzeugen, da ja ein ganzer Speicherzugriff entfällt. Die Zahl, auf die es ankommt, ist bereits im Mnemonic kodiert und muss nicht noch von einer anderen Adresse geladen werden.


  Sicher? Ich habe mich allerdings mit der Problematik in den letzten Jahren nicht mehr so sehr beschäftigt, da ich der Meinung bin, dass aktuelle Compiler durchaus in der Lage sind,  auf dieser Ebene Code effizienter zu optimieren als ein menschlicher Programmierer.


----------



## Kachelator (23. Mai 2004)

Ich habe hier gerade zufällig einen zum Thema Optimierung passenden Artikel wiederentdeckt, den ich recht gut finde: Klick


----------



## Endurion (24. Mai 2004)

Es gibt die Möglichkeit, zumindest in Visual Studio, mit

#define MAXSTRING 256
#define ALSSTRING( x ) printf( #x "\n" )

Man beachte das # innerhalb des Makros. Dadurch wird ein Makro als Text eingesetzt.

Zu anderweitigen Problemen mit Defines ist hier ja schon genug gesagt worden. 

Eine andere möglichkeit wären noch enums. Ich erzeuge zum Beispiel Konstanten einer Klasse generell als Member-Enums. Der Default-Namespace bleibt sauber, und Intellisense zeigt mir alle Konstanten an.


----------



## Kachelator (24. Mai 2004)

> _Original geschrieben von Endurion _
> 
> #define MAXSTRING 256
> #define ALSSTRING( x ) printf( #x "\n" )


Das printet "MAXSTRING" und nicht  "256". #x gibt das Token aus, nicht den Wert desselben.  Eignet sich gut, um zu Debugzwecken Variablen zu dumpen, aber nicht, um aus einer Zahl einen String zu machen.


----------



## Endurion (24. Mai 2004)

Hoppla, hab mal wieder zuviel Gutes angenommen.

Stimmt, funktioniert nicht. 

Mea culpa grande maxima. Oder so. 

Benutz enums - beschwöööööör - enuuuuuuums.


And now to something completely different...


----------

