In einigen eingebetteten C-Code für den MC9S12C32-Mikrocontroller habe ich eine zirkuläre Warteschlange (aka Ringspeicher) implementiert mit einem statisch großen Byte-Array und zwei "Zeigern" für die Vorder- und Rückseite der Warteschlange, Das sind in Wirklichkeit nur Indizes für das Array der Warteschlange.C Modul ohne Vorzeichen verursacht Compiler-Warnung
// call unsigned chars bytes
typedef unsigned char byte;
byte trear = 0; // SCI transmit display buffer IN index
byte tfront = 0; // SCI transmit display buffer OUT index
byte tsize = 16; // size of transmit buffer
byte tbuf[16]= {0};// SCI transmit display buffer
anzumerken, dass trear
der tatsächliche Index des hinteren Elements ist, aber tfront
eins weniger als die tatsächliche Index des Frontelement (je 16 natürlich auf Modulo). So zum Beispiel, wenn mein Puffer enthielt „Hallo“, es könnte wie folgt aussehen (wo leere Slots sind Müll-Wert):
_________________________________
| | |h|e|l|l|o| | | | | | | | | |
^ ^
front rear
Wenn es Zeit ist, einen Byte aus der Warteschlange zu entfernen, ich dies tun:
Das alles funktioniert gut - zumindest hat mein Programm keine Fehler in Bezug auf dieses Fragment gezeigt. Allerdings, wenn ich dieses Programm zu kompilieren, mein Compiler warnt mich über die Linie markiert (A)
im Fragment oben, beschwerte:
Warnung: C2705: Möglicher Datenverlust
main.c Linie 402
Linie 402 ist Linie (A). Ich sollte beachten, dass ich nicht gcc oder ähnliches verwende; Ich kompiliere in der CodeWarrior IDE von Freescale, die mir manchmal andere etwas mysteriöse Warnungen gegeben hat. In einem Versuch, loszuwerden, die Warnung zu erhalten, schrieb ich das Fragment wie oben:
// increment front index mod tsize
tfront = (tfront + 1 >= tsize) ? 0 : tfront + 1; // (B)
// get character to transmit
byte outputChar = tbuf[tfront];
jedoch mein Compiler gibt immer noch die gleiche Warnung, diesmal über Linie (B)
. Vielleicht sagt der Compiler mir, dass in der Anweisung (tfront + 1 >= tsize)
, tfront
255 vor der Ausführung und Überlauf sein könnte. Natürlich weiß ich, dass das nicht passieren wird, aber mein Compiler nicht. Wenn das der Fall ist, warum war Linie (A)
ein Problem? Im Grunde würde ich gerne wissen, worüber der Compiler unglücklich ist.
Da meine Frage eingeben aus, habe ich es gelöst, indem tsize
von einem Variablentyp zu einem Präprozessordefinition ändert (das heißt, #define TSIZE 16
). Meine Frage steht immer noch.
Einige verwandte Fragen:
unsigned overflow with modulus operator in C
modulus operator with unsigned chars
Beachten Sie, dass, wenn 'tsize' garantiert werden kann, eine Potenz von 2 sein, es effizienter ist, eine Bit-Maske zu verwenden, und das auch ordentlich vermeidet diese Warnung ohne Besetzung. Also für einen Puffer von 16 Elementen, 'tfront | = 0x0f' statt' tfront% = 16'. Im allgemeinen Fall ist für jede 'tsize', die eine Potenz von 2 ist, die erforderliche Mod-Maske 'tsize - 1'. – Clifford
@Clifford Wenn die Warnung durch die Erweiterung der Erweiterung auf 'lval = expr;' verursacht wird, wobei 'lval' den Typ' byte' und 'expr' den Typ' int' hat, vermeidet die Verwendung einer Bitmaske nicht die Warnung: ' tfront & = mask; 'expandiert nach' tfront = tfront & mask; 'und' tfront & mask' hat den Typ 'int' aus dem gleichen Grund 'tfront% size' tut (C99 6.3.1.1:2 und 6.3.1.8:1" the Integer-Promotions werden für beide Operanden ausgeführt "). –
@Clifford Zusätzlich muss der bitweise Operator richtig eingestellt werden. Meintest du "&"? –