2016-04-30 15 views
6

Recentemente cppcheck sollevato un errore nel codice C, che ha la struttura:L'ordine di valutazione con operatore e assegnazione di virgola in C è prevedibile?

((void)(value_prev = value), value = new_value()) 

Nella maggior parte dei casi questo può essere divisa su 2 righe, tuttavia ci sono alcuni casi questo è utile avere in una singola istruzione.

In pratica ho trovato questo funziona con compilatori popolari (GCC/Clang/MSVC), che non danno alcun avviso (anche con livelli di avviso impostati al massimo). Codice


Esempio:

#include <stdio.h> 

int get_next(int i); 

int main() { 
    int i = 0, i_prev = 10; 
    do { 
     printf("%d\n", i); 
    } while ((void)(i_prev = i), 
      (i = get_next(i)) != 10); 
} 

CppCheck 1.73 (più tardi al momento della scrittura) dà un errore con questo codice:

(error) Expression '(void)(i_prev=i),(i=get_next(i))!=10' 
depends on order of evaluation of side effects` 

Mentre il codice potrebbe essere cambiato a quietarmi l'avvertimento, l'ordine è davvero indefinito?

+1

Potrebbe essere che get_next (i) è una macro, come #define getnext (i) i ++? – gnasher729

+1

No, in questo caso è definito come una funzione, cppcheck restituisce l'errore su questo codice senza alcuna modifica. – ideasman42

risposta

8

L'ordine è definito, poiché tra loro è presente un punto di sequenza. Vedere ISO/IEC 9899 6.5.17:

L'operando di sinistra di un operatore virgola viene valutato come espressione di annullamento ; c'è un punto di sequenza dopo la sua valutazione. Quindi viene valutato l'operando di destra; il risultato ha il suo tipo e valore. 95) Se si tenta di modificare il risultato di un operatore virgola o di accedervi dopo il successivo punto di sequenza, il comportamento non è definito.

Essi poi dare un esempio esplicito:

Nella chiamata funzione
f(a, (t=3, t+2), c)
la funzione ha tre argomenti, il secondo dei quali ha il valore 5.

Non sono del tutto sicuro del motivo per cui CppCheck lo stia segnalando.

+0

Il punto di sequenza non è un testo C++? – Alex

+0

@Alex Se lo è, allora C99 lo ha preso in prestito da C++. Non ho alcuna specifica C prima del C99 da confrontare. –

Problemi correlati