Ja, aber Sie werden wahrscheinlich eine weitere Warnung erhalten.
Der Standard Weg dies zu tun ist: (void)iid;
.
Sehr technisch, dies noch iid
in ein Register geladen werden konnte und nichts tun. Zugegeben, das ist im Compiler-Teil extrem doof (ich bezweifle, dass jemand das jemals tun würde, wenn es den Compiler löscht), aber es ist ein ernsthafteres Problem, wenn der zu ignorierende Ausdruck etwas ist, das beobachtbares Verhalten betrifft, wie Aufrufe von IO-Funktionen oder Lesen und Schreiben von volatile
Variablen.
Dies bringt eine interessante Frage auf: Können wir einen Ausdruck nehmen und komplett ignorieren Sie es?
Das heißt, was wir jetzt haben, ist dies:
#define USE(x) (void)(x)
// use iid in an expression to get rid of warning, but have no observable effect
USE(iid);
// hm, result of expression is gone but expression is still evaluated
USE(std::cout << "hmmm" << std::endl);
Dies liegt in der Nähe einer Lösung:
// sizeof doesn't evaluate the expression
#define USE(x) (void)(sizeof(x))
Aber irgendwie:
void foo();
// oops, cannot take sizeof void
USE(foo());
Die Lösung ist zu einfach:
// use expression as sub-expression,
// then make type of full expression int, discard result
#define USE(x) (void)(sizeof((x), 0))
Das garantiert keine Operation.
Edit: Die oben in der Tat keine Wirkung garantiert, aber ich gepostet ohne Prüfung. Beim Testen wird zumindest in MSVC 2010 erneut eine Warnung generiert, da der Wert nicht verwendet wird. Das ist nicht gut, Zeit für mehr Tricks!
Erinnerung: Wir möchten einen Ausdruck "verwenden", ohne ihn zu bewerten.Wie kann das gemacht werden? Wie folgt aus:
#define USE(x) ((void)(true ? 0 : (x)))
Dies hat ein einfaches Problem wie beim letzten Mal (schlechter tatsächlich), dass (x)
Bedürfnisse zu int
konvertierbar sein. Dies ist wiederum trivial zu beheben:
#define USE(x) ((void)(true ? 0 : ((x), 0)))
Und wir sind wieder auf gleiche Art von Wirkung, die wir letztes Mal (keine) hatten, aber diesmal x
„verbraucht“, so bekommen wir keine Warnungen . Richtig gemacht?
Es ist eigentlich immer noch ein Problem mit dieser Lösung (und wurde in der letzten un-Lösung als gut, aber unbemerkt), und es kommt in diesem Beispiel folgenden:
struct foo {};
void operator,(const foo&, int) {}
foo f;
USE(f); // oops, void isn't convertible to int!
Das heißt, wenn Der Typ des Ausdrucks (x)
überlädt den Komma-Operator auf etwas, das nicht in int
konvertiert werden kann, die Lösung schlägt fehl. Sicher, unwahrscheinlich, aber aus Gründen völlig über Bord gehen, können wir das Problem beheben mit:
#define USE(x) ((void)(true ? 0 : ((x), void(), 0)))
wir am Ende wirklich mit Null stellen Sie sicher. This trick brought to you by Johannes.
auch wie bereits erwähnt, wenn die oben nicht genug war, ein dumm genug Compiler könnten möglicherweise „load“ der Ausdruck 0
(in ein Register oder etwas), dann ist es ignorieren.
Ich denke, es ist unmöglich, das loszuwerden, da wir schließlich einen Ausdruck brauchen, der zu einer Art von Art führt, die man ignorieren kann, aber wenn ich jemals darüber nachdenke, füge ich sie hinzu.
Wird dadurch nicht die Warnung "Aussage hat keine Wirkung" ausgelöst? – falstro
@roe: Es ist nicht auf Visual C++. Vielleicht ist es bei einigen anderen Compilern. – sharptooth
Wenn zwischen der Deklaration und der Anweisung Sie den Präprozessor missbrauchen, könnte es einen Effekt haben. Zum Beispiel '#define variableName exit (-1)' – Benoit