C / C ++: quali avvertenze di conversione hanno senso nella pratica?

5

Le conversioni implicite C / C ++ possono causare errori. Ecco un esempio:

int foo, bar;
scanf("%d", &foo);
scanf("%d", &bar);
float foobar = foo / bar;

Se inserisco 7 e 2 , non è 3.5 come previsto - è 3 - > bug (ignoriamo l'overflow del buffer).

gcc's -Wconversion avverte su questo tipo di cose, quindi l'ho acceso. Ma mi sembra che stia andando oltre le righe con gli avvertimenti. Ad esempio, questo:

int foo;
float bar;
scanf("%d", &foo);
scanf("%f", &bar);
float foobar = foo / bar;

Provoca un avvertimento:

warning: conversion to 'float' from 'int' may alter its value [-Wconversion]

Anche se funziona come previsto, restituendo 3.5 quando inserisco 7 e 2 . So che float non può rappresentare con precisione tutti i possibili valori int, ma mi sto chiedendo se aggiungere un cast qui faccia qualcosa per aiutare - oltre ad aggiungere altro codice. Nell'esempio sopra, il cast di uno dei valori int dell'espressione float ha effettivamente modificato il risultato, non sostituendo un cast implicito di uno esplicito in questo esempio.

Questo per gli avvisi di conversione float in int, ma non è tutto. C'è anche la segnalazione di avvisi di conversione. Esempio tradizionale:

std::vector<char> chars = get_chars();
for (int i = 0; i < chars.size(); i++)
    std::cout << chars[i] << std::endl;

Causa questo avviso:

warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

Potrei usare il più ingombrante unsigned int per la variabile indice, che richiederà un ulteriore casting quando eseguo i calcoli con esso. Tutto per la situazione insolita che ho tra 2^31 + 1 e 2^32 elementi nel mio vettore e non faccio alcun calcolo con la variabile index che lo ha lanciato su int.

Quindi, la mia domanda è: quali avvisi di conversione hanno senso nella pratica? L'aggiunta di cast espliciti per risolverli migliora davvero qualcosa?

    
posta futlib 10.08.2014 - 01:27
fonte

3 risposte

10

È un po 'come questo.

  1. La possibilità di utilizzare valori e variabili non firmati e numeri reali di diverse precisioni non sono caratteristiche particolarmente comuni nei linguaggi di programmazione, ma sono fondamentali affinché C / C ++ faccia il suo lavoro.
  2. Il missaggio di tipi aritmetici come questi è una delle principali cause di bug nel software C / C ++ reale e commerciale. Fidati di me, ne ho visti molti.
  3. Quindi gli standard C / C ++ stabiliscono un comportamento di conversione con molta attenzione. Ci sono pagine e pagine su questa roba.
  4. Pertanto chiediamo al compilatore di fare tutto il possibile per aiutarci a trovare ed evitare bug nel mondo di conversione. Alcune cose sono errori (contravvenendo allo standard); altri sono avvertimenti (l'impostazione predefinita è associata a possibili o probabili bug).
  5. Ora tocca a noi identificare le strategie di programmazione che riducono al minimo il rischio di bug e, in particolare, che non attivano gli avvisi. Questo è il nostro lavoro.

I cast sono cattivi. Ogni cast potenzialmente documenti su un bug o un avvertimento o un problema di progettazione. Non possiamo vivere senza di loro, ma meno sono e meglio è. La maggior parte sono evitabili, con un design adeguato.

I tuoi due esempi mi sembrano tutti un codice sbagliato. Nei primi due esempi devi dire al compilatore se usare int, float o double arithmetic, dato che i valori di default potrebbero facilmente essere errati. Il terzo esempio deve utilizzare una variabile di ciclo senza segno. C / C ++ è un coltello molto affilato e hai bisogno di più attenzione per evitare di tagliarti.

    
risposta data 10.08.2014 - 04:52
fonte
1

Con GCC troverai che molti avvertimenti importanti sono già raggruppati in -Wall e -Wextra , è anche utile usare -Werror per trasformare gli avvisi in errori.

    
risposta data 10.08.2014 - 03:16
fonte
0

Il flag -Wconversion fornisce spesso falsi positivi, quindi potrebbe essere una buona idea disattivare questi avvisi a meno che tu non abbia davvero bisogno del rigore.

Nella maggior parte dei casi, trovo che -Wsign-conversion sia più utile in quanto le conversioni non firmate involontarie possono spesso causare errori gravi.

Sarebbe bello se GCC fornisse un flag separato che avverta solo sulle conversioni non di sottotipo (ad esempio int su char ).

    
risposta data 10.08.2014 - 06:09
fonte

Leggi altre domande sui tag