Deppenfrage
-
An welcher Stelle bringt mir das #define aus dem Beispiel Unsicherheit? Gibt es dafür ein Beispiel?
-
Neben den üblichen Problemen von Makros (z.B. dass sie nicht an Scopes gebunden sind) geht sowas bei komplexeren Typen sofort in die Hose. Beispiel:
struct Foobar { ... }; #define PFOOBAR Foobar*Die Konsequenzen kann man sich selbst ausmalen, und es wär vielleicht noch ein bisschen witzig, wenn ich das nicht schon im Real Life gesehen hätte.
-
Ich bitte meine Ignoranz zu entschuldigen, aber ich sehe das Problem einfach nicht:
PFOOBAR pb = new Foobar;Ich kann gerade keine Konsequenz sehen. Wo genau ernte ich denn jetzt Unsicherehit? Wo genau hilft mir denn jetzt "typedef Foobar PFOOBAR;"* weiter, was genau macht den Unterschied zu #define aus?
-
Das Problem ist doch viel EInfacher: Makros sind dumme Textersetzungen vor dem Kompilieren. Es wird einfach nur Copy+Paste von Präprozessor gemacht. Ein Bsp. aus meiner Praxiserfahrung (müsste es sogar hier einen Thread zu geben...).
Ich hatte in meinem Projekt ein Enum (kann mich nicht mehr genau erinnern):
enum { ONE, TWO };So, ich weiß nicht mehr was in dem Enum drin stand, ich mach einfach mal irgendwas. Gut, ich habe kompiliert, alles i.O. Irgendwann ist mir eingefallen, ich muß das Enum erweitern (nichts ungewöhnliches):
enum { ONE, TWO, THREE };Nebenbei habe ich noch andere Sache implementiert. Als ich dann kompiliert habe, hat es einen Compiler-Error gegeben, den ich mir einfach nicht erklären konnte. Ich war am verzweifeln. Also hatte ich hier im Forum gefragt. Am Ende kan heraus, das es in der Windows-SDK (ja!) ein Makro gibt, das sich THREE nennent (wie gesagt, ich weiß nicht mehr wie das Makros hieß, ist auch unwichtig jetzt). Mein THREE wurde vom Präprozessor durch das Win-SDK-Makro ersetzt. Der Compiler konnte natürlcih mit dem enum nichts mehr anfangen. Aber da mir dieses Win-SDK-Makro unbekannt war, bin ich nicht drauf gekommen, das THREE bei Compiletime was gaaaanz anderes drin stehen hat, was natürlich völlig schwachsinnig ist.
Also habe ich dann das gemacht:
enum { one, two, three };NUr wegen des Makros das in einem der Header definiert war, MUSSTE ich mein Enum ändern. Das ist eigentlich schon ziemlich dreist und unverschämt!
Obwohl mein THREE in einem anderen Scope (dem Enum-Scope) welcher wiederrum in einem Namespace war. Man muß sich das mal reinziehen: ich hab meinen eigenen Namespace und werde von einem Makros platt gemacht. 
Also: Makros sind böse und sie können einem bei den einfachsten Aufgaben einen Strich durch die Rechnung machen.
-
#define schrieb:
Ich bitte meine Ignoranz zu entschuldigen, aber ich sehe das Problem einfach nicht:
PFOOBAR pb = new Foobar;Ich kann gerade keine Konsequenz sehen. Wo genau ernte ich denn jetzt Unsicherehit? Wo genau hilft mir denn jetzt "typedef Foobar PFOOBAR;"* weiter, was genau macht den Unterschied zu #define aus?
Du hast Makros nicht verstanden. Makros sind nur Textbausteine, mehr nicht. Der Präprozessor (nicht Compiler) macht ein einfaches Copy+Paste in deinem Sourcecode. Danach sieht dein Source ganz anders aus, als du ihn eingegeben hast. Und DANN erst kommt der Compiler dran, und bekommt den vom Prärpozi geänderten Source. Der Compiler kennt die Makros nicht. Und du (als Mensch), siehst auch nicht was der Compiler bekommt, weil die Textersetzung im Hintergrund passiert... also für dich unsichtbar.
Bei Typedefs und const Variablen wird das alles vom Compiler geprüft.
-
Gut, ich sehe das Problem bei enums. Was ist aber das Problem bei #defines?
#define MYTYPE int //Compiler sieht MYTYPE als int (Präprozessor hat das bereits aufgelöst) MYTYPE n = 1; typedef int MYTYPE; // Compiler sieht MYTYPE als int MYTYPE n = 1;Wo liegt der Unterschied?
-
Du solltest eventuell aufmerksamer lesen. Ist alles schon gesagt.
-
#define schrieb:
Ich bitte meine Ignoranz zu entschuldigen, aber ich sehe das Problem einfach nicht:
PFOOBAR a, b;
-
#define schrieb:
Gut, ich sehe das Problem bei enums. Was ist aber das Problem bei #defines?
#define MYTYPE int //Compiler sieht MYTYPE als int (Präprozessor hat das bereits aufgelöst) MYTYPE n = 1; typedef int MYTYPE; // Compiler sieht MYTYPE als int MYTYPE n = 1;Wo liegt der Unterschied?
Hä? Wie bei Enums und wie bei #defines? Das Enum-Problem ist doch durch ein #define entstanden! Aber es würde nicht nur bei Enums sondern bei jedem anderen Konstrukt auch auftreten, egal ob class, if, while usw.
In deinem EINEM KONKRETEN Beispiel wird nicht viel schlimmes passieren. Aber wird dein Programm jemals aus DIESEM EINEM Einzeiler bestehen? Nein! Du wirst größere Programme schreiben, wo du irgendwann etwas nicht beachten wirst, weil deine Gedanken sich mit einem anderen Problem beschäftigen, was dir dann einen Strich durch die Rechnung machen wird.
Ich drehe mal die Spiess um: Warum streubst Du dich typedefs und const-static Variablen zu benutzen?
Kannst Du uns diese Frage beantworten?
-
Bashar schrieb:
PFOOBAR a, b;Ein ganz hervorragender Hundehaufen, vielen Dank!
-
Artchi schrieb:
Ich drehe mal die Spiess um: Warum streubst Du dich typedefs und const-static Variablen zu benutzen?
Kannst Du uns diese Frage beantworten?Also können wir so sagen: Da wird etwas als falsch hingestellt. Es ist falsch, weil es falsch ist. Das habe ich nicht zu hinterfragen, ich darf das nur abnicken. Du weißt nicht, warum ein #define auf INT in einem großen Programm unsicherer ist als ein typedef auf INT. Aber darum geht es auch gar nicht. Es ist schlecht, weil es schlecht sein muß (schließlich behaupten das alle).
Entschuldige meine Frechheit, Klarheit haben zu wollen. Wie konnte ich nur nach dem Warum fragen. Es wird nicht wieder vorkommen. In Zukunft werde ich auch nur noch stumpf abnicken.
-
Musst dich nicht gleich angepisst fühlen. Habe dich schliesslich ganz normal gefragt.
Ich habe dir doch deine Frage beantwortet: MYTYPE wird dir oder jemand anderes _irgendwann_ ins Knie schiessen. Z.B.:
#define MYTYPE intSo, jetzt steht irgendwo in einer anderen Datei von dir, deines Kollegen, oder ein User der deine Library benutzt sowas:
namespace nasa_project { class MYTYPE { }; }So, was meinst du, wird hier passieren? Genau, der Compiler wird eine Fehlermeldung melden, die dem Schreiber dieser Klasse einfach unverständlich sein wird. Er wird seeeeehr schlau sein müssen, und alle Dateien die er direkt und INDIREKT benutzt, mit der Windows-Textinhalt-Dateisuche "MYTYPE" suchen, um heraus zu finden, das in einer Datei ein Makro MYTYPE definiert ist. Der Aufwand der hier betrieben werden muß, um zu erkennen, was eigentlich los ist, steht zu keinem Verhältnis, wenn man ein sicheres typedef benutzt.
Ich weiß nicht wie ausführlich ist das ganze noch beschreiben soll. Wieviel Beispiele ich noch ausdenken soll.
Dein Problem wird wohl sein, das du noch nie in solch einer Situation warst. Was ist wenn du mit jemandem zusammen an einem Projekt arbeitest? Soll er JEDES Makro von dir kennen, um nicht in diese Falle zu tappen? Nein, muß er nicht! Stell dir mal ein OpenSource-Projekt vor, wo 20 Leute auf der Welt dran arbeiten. Muß jetzt jeder jede Eventualität kennen? Obwohl vielleicht mit einem typedef das Problem erst garnicht auftauchen würde? Es geht darum, das wir eine Programmiersprache benutzen, die einem mächtigen Compiler hat. Und diesen Compiler wollen wir nutzen, wo es geht, und nicht den Präprozessor.
Es hat nichts mit Frechheit von meiner Seite zu tun. Ich wollte dich mit meiner Gegenfrage für dein eigenes Denken _sensibilisieren_! Ich könnte jetzt sagen: eine ganz schöne Frechheit von dir, mir nicht zu antworten, obwohl ich (und andere) uns hier größte Mühe geben, DIR zu helfen. Aber Du solltest vielleicht auch mal auf unsere Gegenfragen eine Antwort geben. Vielleicht ist in deiner Antwort auch die Problemerkennung?
-
Es geht mir keineswegs darum, #define auf Biegen und Brechen zu verwenden. In eigenen Programmen finden sich selbstverständlich auch typedefs wieder, reine Angewohnheit
Da ich aber, wie Du richtig festgestellt hast, nie einer probelmatischen Situation gewesen bin und auch nicht in einem Team mit 20 Leuten arbeite, hat sich ganz einfach die Frage "Was wäre wenn?" gestellt. Nicht mehr, nicht weniger.
Der Vorteil von enums liegt, wie ich finde, klar auf der Hand. Nicht aber der von typedefs. Bashar hat mir ja nun einen sehr guten Hundehaufen gelegt, in den ich Tappsen kann. Du hast jetzt noch einen sehr schönen Zweiten dazugelegt, denn an fürchterliche Fehlermeldungen hätte ich als Letztes gedacht.
Alles was ich wollte, war etwas Licht im Dunkel. Und das habe ich ja nun.
