Überprüfen Sie, ob die Variable unbekannter Signedness im Intervall ist

8

In einigen C99-Code muss ich überprüfen, ob die Variable i im Intervall [0, max] ist, wobei max bekanntermaßen positiv ist. Das Problem ist, dass der Typ der Variablen sowohl signiert als auch vorzeichenlos sein darf (indem man typedef ändert). Wie überprüft man am besten, dass die Variable im Intervall ist?

Der direkte Ansatz wäre:

%Vor%

Dies funktioniert gut, wenn wir typedef int my_type; haben. Aber wenn my_type unsigniert ist (d. H.% Co_de%), ist typedef unsigned int my_type; immer wahr und Compiler werden (zu Recht) davor warnen, was ich vermeiden möchte. (Ich möchte diese Warnung nicht ausschalten, da sie nützlich ist, wenn solche Vergleiche tatsächlich unbeabsichtigt sind, und das Ignorieren von Compilerwarnungen ist keine gute Idee.)

Meine aktuelle Idee ist, i >= 0 auf einen vorzeichenlosen Typ zu setzen und einfach die obere Grenze zu prüfen:

%Vor%

Wenn der signierte Typ eine Zweierkomplementdarstellung hat, sollte jeder negative Wert größer als i sein, wenn er einmal in die unsignierte Version umgewandelt wurde, richtig? Wenn ja, sollte das funktionieren. Ich bin jedoch unsicher, ob dies ein sinnvoller Ansatz ist. Ist es beispielsweise sicher anzunehmen, dass signierte Typen auf allen Plattformen Zweierkomplement verwenden? Gibt es einen besseren Weg, dies zu tun?

    
Fredrik Savje 14.02.2016, 04:00
quelle

5 Antworten

7

Prüfe gegen 0 und max . Vermeiden Sie jedoch einen direkten >= 0 Test.

Casting ist ein Problem, da es den Wert in einigen Implementierungen definiert einschränken kann.

%Vor%

Ich werde darüber noch etwas nachdenken.

    
chux 14.02.2016, 04:26
quelle
3

Ich denke, das sollte den Compiler abschalten:

%Vor%     
sh1 14.02.2016 04:48
quelle
2

Vielleicht ist das ein anderer direkter Ansatz:

%Vor%     
Sun Qingyao 14.02.2016 04:26
quelle
2

Eine einfache Lösung ist ein zweiseitiger Test.

Das einzige wirklich verlorene Attribut ist die mäßige Effizienz / Leistung. Keine anderen Probleme.

Obwohl das OP dies sicherlich in Betracht gezogen hat, sollte jede Lösung als Referenz dagegen abgewogen werden.

%Vor%     
chux 14.02.2016 15:54
quelle
2

Wenn Ihr Compiler das unterstützt, glaube ich, dass die sauberste Lösung darin besteht, den Code unverändert zu lassen, aber die Anweisung #pragma zu verwenden, um die falsche Warnung lokal zu deaktivieren. Zum Beispiel würde für GCC 4.6.4+ das Folgende Mach den Trick :

%Vor%

Offenbar sollte das exakt gleiche #pragma s auch für Clang funktionieren , da es die Syntax von GCC imitiert. Andere Compiler können eine ähnliche Syntax haben (zB #pragma warning( disable: ... ) für Visual C / C ++ ), und es sollte möglich sein, Präprozessordirektiven zu verwenden, um die entsprechenden #pragma s für jeden Compiler auszuwählen.

Der Hauptnachteil dieser Methode ist ästhetisch - sie wirft den Code mit hässlichem #pragma s aus. Das würde ich jedoch als Vorzug ansehen, wenn Sie Ihren Code absichtlich verdecken (und möglicherweise sogar de-optimieren), nur um eine Compilerwarnung zu vermeiden. Zumindest ist es mit dem #pragma s für den nächsten Programmierer, der den Code liest, warum er so geschrieben ist, klar.

Um dies übersichtlicher und portabler zu machen, können Sie den C99 _Pragma() -Operator verwenden um Makros zu definieren, die die Warnungen deaktivieren und wieder aktivieren, z so:

%Vor%

und benutze sie so:

%Vor%

Alternativ könnten Sie, wenn Sie Compiler vor C99 unterstützen möchten, ein Paar Header-Dateien ( ohne beliebige Include-Wächter!) erstellen, die so etwas wie warnings_off.h und warnings_restore.h enthalten Entsprechende #pragma für jeden Compiler und dann den Code, für den Sie Warnungen deaktivieren möchten, mit:

%Vor%     
Ilmari Karonen 14.02.2016 13:35
quelle

Tags und Links