2011-12-19 16 views
5

Quando provo a compilare il seguente programma C++ utilizzando il compilatore Visual Studio 2010 C++ (X86) con livello di avviso/W4 abilitato, viene visualizzato un avviso di mancata corrispondenza firmato/non firmato linea segnataC++: mancata corrispondenza firmato/non firmato quando si utilizzano solo tipi non firmati

#include <cstdio> 
#include <cstdint> 
#include <cstddef> 

int main(int argc, char **argv) 
{ 
    size_t idx = 42; 
    uint8_t bytesCount = 20; 

    // warning C4389: '==' : signed/unsigned mismatch 
    if (bytesCount + 1 == idx) 
    { 
     printf("Hello World\n"); 
    } 

    // no warning 
    if (bytesCount == idx) 
    { 
     printf("Hello World\n"); 
    } 
} 

Questo mi confonde, dal momento che sto usando solo i tipi senza segno. Dal confronto

bytesCount == idx 

non causa tale avviso, probabilmente ha a che fare con una strana conversazione implicita che accade qui.

Quindi: qual è il motivo per cui ricevo questo avviso e in base a quali regole avviene questa conversazione (se questo è il motivo)?

risposta

5

1 è un int. Il tipo di un'espressione aritmetica integrale dipende dai tipi coinvolti. In questo caso, si dispone di un tipo unsigned e di un tipo in cui il tipo unsigned è più piccolo del tipo signed. Questo rientra standard ++ C sulle espressioni (sezione 5.10 [expr]):

Altrimenti, se il tipo dell'operando di tipo intero con segno può rappresentare tutti i valori del tipo dell'operando con unsigned tipo intero, l'operando con tipo intero senza segno deve essere convertito nel tipo di operando con tipo intero con segno.

cioè il tipo dell'espressione bytesCount + 1 è int che viene firmato per impostazione predefinita.

9

1 è un letterale firmato. Prova con BytesCount + 1U.

Il compilatore è probabilmente creando un valore temporaneo del tipo firmato dovuto all'aggiunta di valori e senza segno (bytesCount + 1)

3

Dal 1 è di tipo int dell'espressione bytesCount + 1 è int (con segno).

Infatti quando un tipo più piccolo int viene usato in un'espressione matematica è promosso int, quindi, anche + bytesCount e bytesCount + bytesCount sono considerati int e non uint8_t (mentre bytesCount + 1U è un unsigned int dato che è maggiore di int) .

Le uscite following program per tre volte true.

#include <iostream> 

int main() 
{ 
    unsigned short s = 1; 
    std::cout << (&typeid(s + 1U) == &typeid(1U)) << std::endl; 
    std::cout << (&typeid(+ s) == &typeid(1)) << std::endl; 
    std::cout << (&typeid(s + s) == &typeid(1)) << std::endl; 
} 
1

Le altre risposte indicano già che bytesCount + 1 viene interpretato come signed int. Tuttavia, vorrei aggiungere che in bytesCount == idx, bytesCount è anche interpretato come signed int. Concettualmente, viene prima convertito in signed int e successivamente viene convertito in unsigned int. Il tuo compilatore non avvisa di questo, perché ha abbastanza informazioni per sapere che non c'è davvero un problema. La conversione a signed int non può probabilmente rendere negativo bytesCount.Il confronto con bytesCount + 1 è ugualmente valido, ugualmente sicuro, ma solo leggermente più complesso da rendere il compilatore non più riconoscibile come sicuro.

+0

E come dire al compilatore di non avvertirmi di tale problema, se è chiaro dal codice del programma che il confronto è sicuro, ma non voglio disabilitare gli avvertimenti per l'intero file, e non voglio rendere il codice brutto per evitarlo. Esistono modi per raggiungere questo obiettivo? – Arkady

+0

@Arkady Se il compilatore è configurato per avvisare del codice, non si desidera modificare il codice (perché sarà più brutto) e non si desidera modificare la configurazione del compilatore (perché sopprimerà l'utilità avvertenze), non stai lasciando aperte molte opzioni. L'unica opzione che posso pensare di non aver ancora escluso è l'hacking sul compilatore per migliorare la sua analisi. – hvd