Makro funktioniert nicht, warum?
-
wieso bist du auf Makros deart fixiert? Makros haben den großen Nachteil, dass sie nicht Typsicher sind und undefiniertes Verhalten hervorrufen können, was sehr schwer zu debuggen ist. Für die Potenz solltest entweder eine Funktion selber schreiben, oder man: pow aus
math.h
verwenden.
-
supertux schrieb:
Makros haben den großen Nachteil, dass sie nicht Typsicher sind und undefiniertes Verhalten hervorrufen können, was sehr schwer zu debuggen ist.
Hmm, Funktionen können nichts Undefiniertes "hervorrufen"?
-
Ganz kurz: Makros sind Scheisse!
-
abc.w schrieb:
Ganz kurz: Makros sind Scheisse!
Klar. Und ein Hammer auch, sobald du deinen Daumen getroffen hast?
-
Es ist mit Makros sehr viel leichter, Unfug zu machen, weil sie sich nicht an die üblichen Lookup-Regeln halten - Scopes interessieren sie nicht. Unter Windows machen beispielsweise die Makros "min" und "max" aus <windows.h> regelmäßig Probleme.
Zwar ist diese Problematik in C++ gravierender als in C, nichtsdestoweniger empfiehlt sich im Umgang mit Makros große Vorsicht. Sie können unerwünschte Nebeneffekte auf bestehenden Code haben, und diese können wenig offensichtlich und dementsprechend schwer zu beheben sein.
-
seldon schrieb:
Unter Windows machen beispielsweise die Makros "min" und "max" aus <windows.h> regelmäßig Probleme.
Wie sind die definiert?
-
mngbd schrieb:
seldon schrieb:
Unter Windows machen beispielsweise die Makros "min" und "max" aus <windows.h> regelmäßig Probleme.
Wie sind die definiert?
#ifndef NOMINMAX #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #endif /* NOMINMAX */
-
Und die machen Probleme mit Scopes?
-
mngbd schrieb:
Klar:
#include <math.h> #define macro(base, exponent) (pow(base, exponent))
Na toll, damit schreibe ich die Funktion aber nicht selbst, sondern benenne eine in math.h vorhandene um.
Sonst noch vorschläge ?
-
jizzer schrieb:
Sonst noch vorschläge ?
Für beliebige Exponenten sind mir keine problemlosen bekannt. Aber wenn du uns sagst, wofür du das brauchst, können wir vielleicht eines konstruieren, das zumindest die Probleme vermeidet, die du nicht haben willst.
Editgrammatik
-
Natürlich machen die Probleme mit Scopes. Der häufigste Zusammenhang ist in C++ mit numeric_limits, etwa
#include <limits> #include <windows.h> // ... double d = std::numeric_limits<double>::max(); // KAWUMM!
aber in reinem C kann einem sowas beispielsweise mit Funktionszeigern leicht auseinanderfliegen. Nimm an, ich modelliere ein Objektsystem in C und habe darin etwa folgendes:
struct collection { void *max(collection *self, int (*compare)(void*, void*)); }; int compare_int(void *p, void *q) { return *(int*)p < *(int*)q; } /* ... */ collection c; /* Fülle collection */ int x = *(int*)c.max(&c, int_compare);
Da definiere mal so ein max vor und sag mir, ob du die Fehlermeldungen noch verstehst.
Was diesen Use-Case angeht, es macht keinen Sinn, das mit Makros zu versuchen. Es mag in manchen Compilern Erweiterungen geben, die so etwas ermöglichen, aber da sich das ganze mit einer Funktion lösen lässt, besteht wirklich keinerlei Grund, auf Makros zurückzugreifen - mit einer Funktion hast du all diese Probleme nicht, und du kannst Dinge damit machen, die mit einem Makro nicht gehen (es gibt beispielsweise keine Zeiger auf Makros).
-
Dann halt nich. dann muss ich mich wohl mit bestimmten fällen wie x² oder x³ zufrieden geben. wobei.. könnte man bspw.folgendes
#define pow(x) (x) * (x)
.
.
.
pow(pow(x));tun, also Makros verschachteln?
-
abc.w schrieb:
Ganz kurz: Makros sind Scheisse!
Nein, das sind sie auch nicht. Manchmal ersapren Makros verdammt viel getippe:
Z.b. in einer Bibliothek habe ich (Makros und Inhalt weitgehend geändert)
#define get_value_typed(type, type_short_name, c_type)\ int get_obj_ ##type_short_name(data_obj *cv, c_type *val)\ {\ int ret;\ if(cv == NULL || val == NULL)\ return 0;\ if ((cv->dtype != TYPE_INVALID) && (cv->dtype != type)) return 0;\ ret = obj_request(cv, cv->read_to);\ if(ret == 0)\ return 0;\ *val = (c_type) obj_get_value(cv);\ return 1; } get_value_typed(TYPE_I8, i8, int8_t); get_value_typed(TYPE_U8, u8, uint8_t); get_value_typed(TYPE_I16, i16, int16_t); get_value_typed(TYPE_U16, u16, uint16_t); get_value_typed(TYPE_I32, i32, int32_t); get_value_typed(TYPE_U32, u32, uint32_t);
Damit hab ich sofort die Implementierung für Funktionen:
int get_obj_i8(data_obj *cv, int8_t); int get_obj_u8(data_obj *cv, uint8_t); ....
mngbd schrieb:
supertux schrieb:
Makros haben den großen Nachteil, dass sie nicht Typsicher sind und undefiniertes Verhalten hervorrufen können, was sehr schwer zu debuggen ist.
Hmm, Funktionen können nichts Undefiniertes "hervorrufen"?
ja, das stimmt. Was ich aber sagen wollte, dass man mit Makros viel leichter nicht offensichtliche Fehler machen kann.
-
Der Typ hier verwendet pow als Makro. Aber wenn ich das ausführen will gehts nicht.
http://c-buch.sommergut.de/Kapitel12/Symbolische-Konstanten-und-Makros.shtml
-
Er erläutert im umgebenden Text aber auch, warum das keine gute Idee ist.
-
Ich hab's jetzt nicht alles gelesen, aber warum kann es den keine Funktion sein?
-
Kann auch ne Funktion sein. Die Frage war eher interessehalber. In dem Link (s.o.) steht, trotz der Hinweise, warum das eine Fehlerquelle sein kann, dass man es so als Makro benutzen kann - genau das funktioniert aber nicht (bei ms visual studio 2008 zumindest), also hat er unrecht ?
-
jizzer schrieb:
Kann auch ne Funktion sein. Die Frage war eher interessehalber. In dem Link (s.o.) steht, trotz der Hinweise, warum das eine Fehlerquelle sein kann, dass man es so als Makro benutzen kann - genau das funktioniert aber nicht (bei ms visual studio 2008 zumindest), also hat er unrecht ?
Bei mir funktioniert sein Beispiel. Also machst du falsch, da du aber nicht sagt, was passiert, kann dir eh keiner helfen :p
-
#include <stdio.h> #define pow(a, b) (double atemp = a; for(;b>0;b--)a*=atemp;) void main() { double base = 2; int exp = 3; printf("Ergebnis: %3f", pow(base, exp)); }
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2146: syntax error : missing ')' before identifier 'atemp'
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2065: 'atemp' : undeclared identifier
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2106: '=' : left operand must be l-value
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2143: syntax error : missing ')' before ';'
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2065: 'atemp' : undeclared identifier
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2059: syntax error : ')'
1>d:\daten\z002nweb\inout\inout\inoutsource.c(10) : error C2059: syntax error : ')'
-
Makro haben keine Return-Wert.