(noob-frage) define oder doch typedef...
-
Du hast das #define falsch herum betrachtet -
#define name irgendwas
ersetzt (fast) jedes Vorkommen von 'name' im Quelltext durch 'irgendwas' (und die beiden Makros, die du dort erwähnt hast, ersetzen die Wörter 'begin' und 'end' durch geschweifte Klammern - das ist etwas für Umsteiger, die C unbedingt mit Pascal-artiger Syntax programmieren wollen ;)).PS: Ja, der Compiler kann mit typedef's besser umgehen (von den #defines sieht er überhaupt nichts mehr, die werden vorher vom Präprozessor ausgewertet).
Ein Beispiel (bin mir nicht 100% sicher, ob das klappt):
//legt einen Arbeitsdatentyp für eine Bibliothek fest //#define type double typedef double type; //diese Funktion hat nichts mit der obigen Bibliothek zu tun, sondern wird nur zufällig im selben Programm verwendet int irgendwas(int type) { ... }
Mit dem typedef müsste das problemlos klappen - die lokale Variable type überdeckt den gleichnamigen Datentyp. Wenn du den ersetzt durch das #define, sieht der Compiler plötzlich eine Funktion
int irgendwas(int double)
- und eine Variable darf nicht 'double' heißen.(noch schlimmer wird's, wenn du Makros mit Parametern definierst und dann sicherstellen willst, daß sie sich wie inline-Funktionen verhalten)
-
#define NUDELN "Spaghetti " "Maccaroni" int main() { puts(NUDELN); return 0; }
-
Ok, Danke für Eure Antworten. Also kann es mit #define zu ungewollten Effekten bzw. schwer auffindbaren Fehlern kommen und mit typedef eher weniger - das macht die Sache etwas klarer.
Sehe ich das jetzt richtig:Mir ist klar, dass ich mit #define <Bezeichner> <Ersatz> einem gültigen Bezeichner einen Alias zuordne, den ich stattdessen im Quelltext verwenden kann (Makro)... Wenn ich jetzt zufällig den Orginal-Bezeichner im Quelltext nutze, wird der dann immer durch den Alias ersetzt!?
Und hier
#define UBYTE unsigned char
wird einem Bezeichner den es noch nicht gibt (UBYTE) ein Datentyp zugeordnet!? Wenn also der Bezeichner im Quelltext vom Präprozessor durch den Alias ersetzt wird, heißt das: Ich schreibe UBYTE und der Compiler sieht unsigned char!?
Daher nutzt "mmmmh lecker" in main() den Bezeichner NUDELN und der Alias (Spaghetti / Maccaroni) wird theoretisch ausgegeben!? (sehr kulinarisches Beispiel - gut, dass ich schon Mittag hatte)
-
Kolumbus schrieb:
Und hier
#define UBYTE unsigned char
wird einem Bezeichner den es noch nicht gibt (UBYTE) ein Datentyp zugeordnet!?
Kein Datentyp, einfach eine Zeichenfolge (der Präprozessor kennt keine Datentypen und dergleichen, der kennt nur "Token" (das sind die Grundelemente der Sprache, z.B. '+', 'UBYTE' oder '>>')).
Wenn also der Bezeichner im Quelltext vom Präprozessor durch den Alias ersetzt wird, heißt das: Ich schreibe UBYTE und der Compiler sieht unsigned char!?
Ja.
Daher nutzt "mmmmh lecker" in main() den Bezeichner NUDELN und der Alias (Spaghetti / Maccaroni) wird theoretisch ausgegeben!? (sehr kulinarisches Beispiel - gut, dass ich schon Mittag hatte
)
Genau genommen wird erst NUDELN ersetzt durch
"Spaghetti " "Maccaroni"
, danach werden dies beiden String-Literale zu einem zusammengefasst und der Compiler sieht "Spaghetti Maccaroni".
-
Warum muss man bei Lernprozessen immer eine Tür finden, nur um dann gleich wieder gegen eine Mauer zu rennen? "Token" also, hab ich auch noch nie gehört...
Demnach wird UBYTE durch #define zu einem "Grundelement der Sprache" (Token) hinter dem sich die Zeichenfolge "unsigned char" verbirgt. Dieses Token ersetzt der Präprozessor durch die Zeichenfolge. Für den Compiler ist das (in diesem Fall) dann allerdings keine schnöde Zeichenfolge mehr, sondern (in diesem Fall) was ganz was Feines, nämlich ein Datentyp!Ist es etwas dem Compiler unbekanntes, schaut er ins Handbuch (defines).
#define begin {
funktioniert demzufolge, weil der Präprozessor das "{" stehen lässt und der Compiler ins Handbuch (defines) schaut und feststellt: "jo, das is n begin"!
-
Nicht ganz, aber es geht in die richtige Richtung.
Zunächst: Ein "Token" ist einfach nur eine Zusammenfassung von Zeichen, die später geschlossen verarbeitet werden können - aus den Zeichen 'U' 'B' 'Y' 'T' 'E' wird das Token "Bezeichner UBYTE", aus zwei aufeinanderfolgenden '>' das Token "Rechtsshift-Operator" etc. Der Präprozessor zerlegt den Porgrammtext in solche Token (und ersetzt dabei einzelne Teile, z.B. den "Bezeichner UBYTE" durch "Typ unsigned char"). Wenn der Compiler später noch etwas findet, was er nicht kennt (oder was an der betrachteten Stelle nicht hinpasst), beschwert er sich bei dir.
Was das
define begin {
angeht - der Compiler kennt die geschweifte Klammer, die in C eine Compound-Anweisung eröffnet, also braucht er nirgends nachschauen, was sie bedeutet. Ein Schlüsselwort "begin" kennt er nicht - und würde sich deshalb beschweren, wenn er es finden würde. Also ersetzt der Präprozessor jedes Vorkommen von "begin" durch die geschweifte Klammer und schon kann der Compiler den Quelltext (der ursprünglich in Pascal-artiger Syntax da stand) verstehen.
-
Yeah - ich danke Dir! *WieWildDurchsBüroHüpf*
Ich glaube ich hab's gerafft! Was hätte ich alles lesen müssen, damit ich das kapiert hätte und vor Allem: Wo steht das so? Und nach dieser Erklärung habe ich jetzt nochmal das ganze Projekt durchforstet und tatsächlich einige begin gefunden... aber nur ganz spärlich gestreut!
Danke nochmal
MfG
-
Und was sich da noch an Zusatzinfo's findet: begin und { (siehe 2. post von volkard)
-
Hey hab define und typedef jetzt verstanden nur was heißt das nun?
#define TipcMsgGetNamedInt2Array(a, b, c, d) TipcMsgNextInt2Array ((a),(c),(d))
Grüße Watercase
-
OK habs verstanden. Somit wird nur an der Stelle eine kürzere Darstellung des Typen vorgenommen.