Wie mit -Wconversion Warnungen von GCC umgehen?
-
10-07-2019 - |
Frage
Ich baue mein Projekt mit -Wconversion Warnflag des GCC. (Gcc (Debian 4.3.2-1.1) 4.3.2) auf einem 64-Bit-GNU / Linux OS / Hardware. Ich bin es nützlich bei der Identifizierung zu finden, wo ich Arten oder verloren Klarheit gemischt habe darüber, welche Arten verwendet werden sollen.
Es ist nicht so hilfreich in den meisten anderen Situationen, in denen es Warnungen aktivieren und ich frage wie kann ich mit diesen beschäftigen bedeuten:
enum { A = 45, B, C }; /* fine */
char a = A; /* huh? seems to not warn about A being int. */
char b = a + 1; /* warning converting from int to char */
char c = B - 2; /* huh? ignores this *blatant* int too.*/
char d = (a > b ? b : c) /* warning converting from int to char */
Aufgrund der unerwarteten Ergebnisse der obigen Tests (Fälle a
und c
) Ich bin auch für diese Unterschiede zu fragen auch erklärt werden.
Edit:? Und ist es über Engineering all diese mit (char)
zu werfen um die Warnung zu verhindern
Edit2: Einige zusätzliche Fälle (im Anschluss an obigen Fällen):
a += A; /* warning converting from int to char */
a++; /* ok */
a += (char)1; /* warning converting from int to char */
Abgesehen davon, was ich frage ist subjektiv, und ich möchte hören, wie andere Leute mit den Konvertierungswarnungen in Fällen wie diesen beschäftigen, wenn man bedenkt, dass einige Entwickler befürworten Entfernen alle Warnungen .
YAE:
Eine mögliche Lösung ist, einfach rechts int
s statt char
s zu benutzen? Naja, eigentlich, nicht nur, dass es mehr Speicher benötigt, ist es langsamer ist auch, wie man durch den folgenden Code demonstriert. Die Mathematik Ausdrücke sind einfach da, die Warnungen zu erhalten, wenn sie mit -Wconversion
gebaut. Ich nahm die Version char
Variablen laufen würde langsamer als die Verwendung von int
s aufgrund der Umbauten, aber auf meinem (64-Bit-Dual-Core-II) System der int
Version ist langsamer.
#include <stdio.h>
#ifdef USE_INT
typedef int var;
#else
typedef char var;
#endif
int main()
{
var start = 10;
var end = 100;
var n = 5;
int b = 100000000;
while (b > 0) {
n = (start - 5) + (n - (n % 3 ? 1 : 3));
if (n >= end) {
n -= (end + 7);
n += start + 2;
}
b--;
}
return 0;
}
Pass -DUSE_INT
auf gcc die int Version des obigen Schnipsel zu bauen.
Lösung
Wenn Sie /* int */
sagen meinst du es eine Warnung über das ist zu geben? Ich sehe keine Warnungen an alle in diesem Code mit gcc 4.0.1 oder 4.2.1 mit -Wconversion
. Der Compiler wandelt diese Aufzählungen in Konstanten. Da alles zum Zeitpunkt der Kompilierung bekannt ist, gibt es keinen Grund, eine Warnung zu erzeugen. Der Compiler kann die ganze Unsicherheit optimieren heraus (die folgende ist Intel mit 4.2.1):
movb $45, -1(%rbp) # a = 45
movzbl -1(%rbp), %eax
incl %eax
movb %al, -2(%rbp) # b = 45 + 1
movb $44, -3(%rbp) # c = 44 (the math is done at compile time)
movzbl -1(%rbp), %eax
cmpb -2(%rbp), %al
jle L2
movzbl -2(%rbp), %eax
movb %al, -17(%rbp)
jmp L4
L2:
movzbl -3(%rbp), %eax
movb %al, -17(%rbp)
L4:
movzbl -17(%rbp), %eax
movb %al, -4(%rbp) # d = (a > b ? b : c)
Dies ist auf Optimierungen ohne sich umzudrehen. Mit Optimierungen, wird es b und d für Sie bei der Kompilierung berechnen und ihre endgültigen Werte codieren (wenn es sie tatsächlich für etwas braucht). Der Punkt ist, dass gcc bereits ausgearbeitet, dass es hier kein Problem sein, weil alle möglichen Werte in einem char
passen.
EDIT: Lassen Sie mich das etwas ändern. Es ist ein möglicher Fehler bei der Zuordnung von b
, und der Compiler wird es nie fangen, auch wenn es sicher ist. Zum Beispiel, wenn b=a+250;
, dann wird dies sicher sein b
überzulaufen, aber gcc eine Warnung nicht erteilen. Es ist, weil die Zuordnung a
legal ist, a
ein char
ist, und es ist Ihr Problem (nicht der Compiler), um sicherzustellen, dass Mathematik nicht überläuft zur Laufzeit.
Andere Tipps
Vielleicht kann der Compiler bereits sehen, dass alle Werte in eine char passen, so dass es Warnung nicht stört. Ich würde die enum
erwarte gleich zu Beginn der Zusammenstellung gelöst werden.