Im folgenden C-Schnipsel, der prüft, ob die ersten beiden Bits einer 16-Bit-Sequenz gesetzt sind:
bool is_pointer(unsigned short int sequence) {
return (sequence >> 14) == 3;
}
Clang-Tidy von CLion gibt mir eine Warnung “Verwendung eines vorzeichenbehafteten Ganzzahloperanden mit einem binären bitweisen Operator”, und ich kann nicht verstehen, warum. Ist unsigned short
nicht unsigniert genug?
Der Code für diese Warnung überprüft ob entweder Operand des bitweisen Operators ist signiert. Es ist nicht sequence
verursacht die Warnung, aber 14
und Sie können das Problem lindern, indem Sie machen 14
unsigniert durch Anhängen von a u
bis zum Ende.
(sequence >> 14u)
Diese Warnung ist schlecht. Wie Rolands Antwort beschreibt, behebt CLion dies.
Es gibt einen Check in Clang-Ordnung, der aufgerufen wird hicpp-signed-bitwise
. Diese Prüfung folgt dem Wortlaut des HIC++-Standards. Diese Norm ist frei verfügbar und sagt:
5.6.1. Verwenden Sie keine bitweisen Operatoren mit vorzeichenbehafteten Operanden
Die Verwendung von vorzeichenbehafteten Operanden mit bitweisen Operatoren unterliegt in einigen Fällen einem undefinierten oder implementierungsdefinierten Verhalten. Daher sollten bitweise Operatoren nur mit Operanden ganzzahliger Typen ohne Vorzeichen verwendet werden.
Die Autoren des HIC++-Codierungsstandards haben die Absicht der C- und C++-Standards falsch interpretiert und sich entweder versehentlich oder absichtlich auf die konzentriert Typ der Operanden statt der Wert der Operanden.
Der Check in clang-tidy setzt genau diese Formulierung um, um diesem Standard zu entsprechen. Dieser Scheck ist nicht als allgemein nützlich gedachtsein einziger Zweck ist es, den armen Seelen zu helfen, deren Programme dieser einen dummen Regel des HIC++-Standards entsprechen müssen.
Der entscheidende Punkt ist, dass ganzzahlige Literale ohne Suffix per Definition vom Typ sind int
, und dieser Typ ist als signierter Typ definiert. HIC++ kommt nun fälschlicherweise zu dem Schluss, dass positive Integer-Literale negativ sein könnten und somit könnten Rufen Sie undefiniertes Verhalten auf.
Zum Vergleich sagt der C11-Standard:
6.5.7 Bitweise Verschiebungsoperatoren
Wenn der Wert des rechten Operanden negativ oder größer oder gleich der Breite des heraufgestuften linken Operanden ist, ist das Verhalten nicht definiert.
Diese Formulierung ist sorgfältig gewählt und betont, dass die Wert des rechten Operanden ist wichtig, nicht sein Typ. Es deckt auch den Fall eines zu großen Werts ab, während der HIC++-Standard diesen Fall einfach vergisst. Deshalb sagen 1u << 1000u
ist in HIC++ ok, während 1 << 3
ist nicht.
Die beste Strategie besteht darin, diese einzelne Prüfung explizit zu deaktivieren. Es gibt mehrere Fehlerberichte für CLion Erwähne dies, und es wird dort behoben.
Update 16.12.2019: Ich habe Perforce gefragt, was die Motivation hinter dieser genauen Formulierung war und ob die Formulierung Absicht war. Hier ist ihre Antwort:
Unser C++-Team, das an der Erstellung des HIC++-Standards beteiligt war, hat sich die von Ihnen erwähnte Stack Overflow-Frage angesehen.
Kurz gesagt, der Verweis auf den Objekttyp in der HIC++-Regel anstelle des Werts ist eine bewusste Wahl, um eine einfachere automatische Überprüfung des Codes zu ermöglichen. Der Typ eines Objekts ist immer bekannt, der Wert jedoch nicht.
- HIC++-Regeln zielen im Allgemeinen darauf ab, “entscheidbar” zu sein. Das Erzwingen gegen den Typ stellt sicher, dass eine entscheidbare Prüfung immer möglich ist, dh. direkt dort, wo der Operator verwendet wird oder wo ein vorzeichenbehafteter Typ in einen vorzeichenlosen umgewandelt wird.
- Die Begründung bezieht sich ausdrücklich auf “mögliches” undefiniertes Verhalten, daher kann eine sinnvolle Umsetzung ausschließen:
- Konstanten, es sei denn, es gibt definitiv ein Problem und
- unsignierte Typen, die zu signierten Typen heraufgestuft werden.
- Daher ist es am besten, wenn CLion die Überprüfung vor der Heraufstufung auf nicht konstante Typen beschränkt.
Ich denke, die Integer-Promotion verursacht hier die Warnung. Operanden kleiner als int werden für den vorzeichenbehafteten arithmetischen Ausdruck zu einer ganzen Zahl erweitert. Ihr Code ist also effektiv return ( (int)sequence >> 14)==3;
was zu der Warnung führt. Versuchen return ( (unsigned)sequence >> 14)==3;
oder return (sequence & 0xC000)==0xC000;
.
Klingt nach einem Fehler.
– Oliver Charlesworth
17. Mai 2018 um 19:26 Uhr
Es wird in JetBrains CLion behoben. Es gibt eine Diskussion von 2018 in Clang-Tidy-Bug 36961ist aber noch nicht behoben.
– Roland Illig
8. Oktober 2019 um 16:04 Uhr
Ich habe den Perforce-Support kontaktiert und um eine Klärung dieses Problems gebeten. Mal sehen, was sie antworten. (Perforce ist der Betreuer des Standards, der von clang-tidy implementiert wird und wiederum in CLion verwendet wird.)
– Roland Illig
12. Dezember 2019 um 23:37 Uhr