In alcuni codici C incorporati per il microcontrollore MC9S12C32, ho una coda circolare (nota anche come buffer circolare) implementata con un array di byte di dimensioni statiche e due "puntatori" per la parte anteriore e posteriore della coda, che sono in realtà solo indici per l'array della coda.Il modulo C senza segno causa il warning del compilatore
// 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
noti che trear
è l'indice effettivo dell'elemento posteriore, ma tfront
è uno inferiore indice effettivo dell'elemento anteriore (soggetto a con modulo 16 naturalmente). Così, per esempio, se il mio tampone conteneva "ciao", che potrebbe assomigliare a questo (dove gli slot vuoto sono i valori della spazzatura):
_________________________________
| | |h|e|l|l|o| | | | | | | | | |
^ ^
front rear
Quando è il momento di rimuovere un byte dalla coda, faccio questo:
// increment front index
tfront++;
// wrap front index if it exceeded bounds
tfront %= tsize; // (A)
// get character to transmit
byte outputChar = tbuf[tfront];
Questo funziona perfettamente - almeno, il mio programma non ha mostrato bug relativi a questo frammento. Tuttavia, quando ho compilare questo programma, il mio compilatore mi mette in guardia circa la linea tracciata (A)
nel frammento di cui sopra, lamentandosi:
Attenzione: C2705: possibile perdita di dati
linea main.c 402
La riga 402 è la linea (A). Devo notare che non sto usando gcc o simili; Sto compilando l'IDE CodeWarrior di Freescale, che a volte mi ha dato altri avvertimenti in qualche modo mistificanti. Nel tentativo di sbarazzarsi di avvertimento, ho riscritto il frammento di cui sopra come:
// increment front index mod tsize
tfront = (tfront + 1 >= tsize) ? 0 : tfront + 1; // (B)
// get character to transmit
byte outputChar = tbuf[tfront];
Tuttavia, la mia compilatore emette sempre lo stesso avvertimento, questa volta sulla linea (B)
. Forse il compilatore mi sta dicendo che nella dichiarazione (tfront + 1 >= tsize)
, tfront
potrebbe essere 255 prima dell'esecuzione e overflow. Certo, so che questo non accadrà, ma il mio compilatore no.
Se questo è il caso, perché la linea (A)
è stata un problema? Fondamentalmente, mi piacerebbe sapere di cosa sia infelice il compilatore.
Dal momento che digitando la mia domanda, ho risolto cambiando tsize
da un tipo di variabile a una definizione di preprocessore (vale a dire, #define TSIZE 16
). La mia domanda è ancora valida, però.
Alcune questioni connesse:
unsigned overflow with modulus operator in C
modulus operator with unsigned chars
Nota che se 'tsize' può essere garantito per essere una potenza di 2, è più efficiente di utilizzare una maschera di bit, e che anche evita ordinatamente questo avvertimento senza un cast. Quindi per un buffer di 16 elementi, 'tfront | = 0x0f' piuttosto che' tfront% = 16'. Nel caso generale per qualsiasi 'tsize' che è una potenza di 2, la maschera mod richiesta è' tsize - 1'. – Clifford
@Clifford Se l'avviso è causato dal assegnazione espansione per 'lval = expr;' 'dove lval' ha tipo' 'byte' e expr' è di tipo' int', quindi utilizzando una maschera di bit non evita l'avvertimento: ' tfront & = maschera; '' espande tfront = tfront & mask; 'e' tfront & mask' ha tipo 'int' per la stessa ragione' tfront% size' fa (C99 6.3.1.1:2 e 6.3.1.8:1 “la le promozioni intere vengono eseguite su entrambi gli operandi "). –
@Clifford Inoltre, è necessario ottenere l'operatore bit a destra. Intendevi '&'? –