?
Der will dich auf den Arm nehmen. Keine Namenskollisionen bei Makros? Lustige Vorstellung.
Makros machen stumpf Textersetzung.
#define MAXIMUM 100
bedeutet, dass danach alle Vorkommen von MAXIMUM im Quelltext durch 100 ersetzt werden. MAXIMUM ist dementsprechend vom Typ int, für den der Standard einen Wertebereich von mindestens -32768 bis 32767 (-215 bis 215 - 1, d.h. 16 Bit breit) garantiert, der aber auf heutigen Maschinen in der Regel (Mikrocontroller ausgenommen) Werte von -2147483648 bis 2147483647 aufnehmen kann (d.h. 32 bit).
Ein Literal ist nicht typlos, und das ist wichtig. Woher diese Idee mit "generischen Typen" kommt, ist mir völlig schleierhaft. Jedenfalls haben Literale Typen wie folgt:
int a = 100;
long b = 100L;
long long c = 100LL;
unsigned d = 100U;
unsigned long e = 100UL;
unsigned long long f = 100ULL;
double g = 3.141;
float h = 3.141F;
long double i = 3.141L;
das überträgt sich auf Makros. Bei Variablenzuweisungen innerhalb eines bestimmten Wertebereichs ist die Angabe eines entsprechenden Suffixes nicht zwingend notwendig, weil die Typumwandlung implizit passiert, aber es kann unter Umständen wichtig werden. Beispielsweise wird
unsigned long long x = 3000000000; // 3 Milliarden
auf Maschinen mit 32-Bit-Integern zu einem Compilerfehler führen, weil das Literal versucht, vom Typ int zu sein, der den Wert nicht fassen kann. Ähnlich wird
unsigned long long x = 1 << 32;
dort nicht machen, wonach es auf den ersten Blick aussieht.
Der Vorteil von Konstanten gegenüber Makros ist, dass sie ein Scope haben, d.h.
{
int const max = 10;
}
// max ist hier nicht mehr bekannt
und dementsprechend nicht Code verändern, der nach ihnen kommt. Wer mal mit windows.h gearbeitet hat, kennt die Problematik - dort werden zwei Makros min() und max() definiert, die regelmäßig nachfolgende Header zerschießen.
Der Nachteil, jedenfalls auf Vor-C99-Compilern, ist, dass sie nicht zur Angabe der Größe eines Arrays benutzt werden können.
int const dimension = 100;
int foo[dimension]; // Darf ein C89-Compiler ablehnen
#define DIMENSION 100
int foo[DIMENSION]; // Darf er nicht ablehnen
Der Grund dafür ist, dass Konstanten in C keine Compilezeit-Konstanten sein müssen. Beispielsweise
void foo(int elems) {
int const dimension = elems * 2;
int foo[dimension]; // Ups.
}
Deswegen wird das erst mit der Einführung von Arrays variabler Länge in C99 möglich. Problematisch ist das, weil ein gängiger C-Compiler - MSVC - bis heute C99 nicht beherrscht. Wobei auch der, wenn ich das richtig im Kopf habe, VLAs kennt, es also eigentlich keinen wirklich guten Grund mehr gibt, Konstanten als Makros zu definieren.
Allerdings muss man anerkennen, dass Makros für diesen Zweck in C durchaus üblich sind. Es ist aber von größer Wichtigkeit, eindeutige Bezeichner zu wählen, sonst läufst du in Gefahr, dich mit Fremdcode zu beißen. MAXIMUM ist ein schlechter Makroname, weil jemand anderes auf die Idee kommen kann, ihn auch zu benutzen. Eine verbreitete Methode, das Problem von Kollisionen zu umgehen, ist ein Präfix - quasi ein Namensraum. Boost.Preprocessor nennt alle seine Makros beispielsweise BOOST_PP_EIGENTLICHER_NAME. Du tätest gut daran, ähnlich zu verfahren.