Domanda

Il seguente codice non dà un avviso con g ++ 4.1.1 e -Wall.

int octalStrToInt(const std::string& s)
{    
    return strtol(s.c_str(), 0, 8);
}

Mi aspettavo un avviso perché strtol restituisce una long int ma la mia funzione è solo restituendo un int pianura. Potrebbero altri compilatori emettere un avvertimento qui? Dovrei cast del valore restituito in int in questo caso come una buona pratica?

È stato utile?

Soluzione

Potrebbe essere necessario il flag -Wconversion per trasformare queste avvertenze su. Tuttavia, non sarà mettere in guardia sui lunga -> int , dal momento che sono della stessa dimensione con GCC (il valore non cambierà a causa della conversione). Ma sarebbe se si converte ad esempio lunga -> breve

Suppongo che semplicemente facendo un cast non sarebbe consigliabile, dal momento che sarebbe solo coprire la possibilità di bug. Sarebbe OK dopo aver verificato che un tale cast non modificherà il valore per placare il compilatore.

Altri suggerimenti

Miglior approccio è:

long x = strtol(...); assert(x <= INT_MAX); return (int)x;

È necessario limits.h e assert.h

Se non si ha accesso a boost::numeric_cast, è possibile scrivere un semplice imitazione:

template <typename T, typename S>
T range_check(const S &s) {
    assert(s <= std::numeric_limits<T>::max());
    assert(s >= std::numeric_limits<T>::min());
    return static_cast<T>(s); // explicit conversion, no warnings.
}

return range_check<int>(strtol(some_value,0,8));

In realtà questo è un po 'un imbroglio, dal momento che non funziona per il galleggiamento tipi punto di destinazione. min() non è lo stesso limite per loro come lo è per i tipi interi, è necessario controllare contro +/- max(). Esercizio per il lettore.

Sia che si utilizzi valere o qualche altro di gestione degli errori dipende cosa si vuole realmente fare per input non valido.

C'è anche boost::lexical_cast (fuori mano, non so come fare che leggere ottale) e stringstream. Leggere il tipo desiderato, non è il tipo che succede ad avere una funzione di libreria C per esso.

Non si vede alcun avvertimento qui, perché il "int" e tipi di dati "long int" sulla tua piattaforma hanno la stessa dimensione e la gamma. A seconda dell'architettura, potrebbero diventare differente.

Per proteggersi da strani errori, utilizzare il controllo gamma. Vi suggerisco di usare std :: :: numeric_limits min / max (vedi).

Dopo la verifica gamma si può tranquillamente utilizzare static_cast o ghisa c-style.

D'altra parte, si può fare affidamento sulla stessa funzionalità implementata in classe std :: stringstream. La conversione con std :: stringstream sarà piattaforma sicura e type-safe per impostazione predefinita.

La maggior parte dei compilatori moderni potranno mettere in guardia circa la conversione e l'eventuale troncamento a seconda del livello di allarme è stato configurato. Su MSVC che è allarme per il livello 4.

Le migliori pratiche potrebbe essere quella di restituire una lunga dalla vostra funzione, e lasciare che il codice chiamante decidere come gestire la conversione. A parte ciò, almeno assicurarsi che il valore che si ottiene indietro dalla strtol si inserisce in un int prima di tornare, come suggerito da Let_Me_Be.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top