Question

The following code does not give a warning with g++ 4.1.1 and -Wall.

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

I was expecting a warning because strtol returns a long int but my function is only returning a plain int. Might other compilers emit a warning here? Should I cast the return value to int in this case as a good practice?

Was it helpful?

Solution

You may need the -Wconversion flag to turn these warnings on. However, it won't warn about long -> int, since they are the same size with GCC (the value won't change because of the conversion). But it would if you convert for example long -> short

I suppose simply doing a cast would not be recommended, since that would just cover up the possibility of bugs. It would be OK after you have checked that such a cast won't modify the value to appease the compiler.

OTHER TIPS

Best approach is:

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

You need limits.h and assert.h

If you don't have access to boost::numeric_cast, you can write a simple imitation:

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));

Actually that's a bit of a cheat, since it doesn't work for floating point destination types. min() isn't the same bound for them as it is for integer types, you need to check against +/- max(). Exercise for the reader.

Whether you use assert or some other error-handling depends what you actually want to do about invalid input.

There's also boost::lexical_cast (off-hand I don't know how to make that read octal) and stringstream. Read the type you want, not the type that happens to have a C library function for it.

You do not see any warning here, because the "int" and "long int" datatypes on your platform have the same size and range. Depending on architecture, they could become different.

To protect yourself from strange errors, use range checking. I suggest you to use std::numeric_limits::min/max (see ).

After range checking you can safely use static_cast or c-style cast.

On the other hand, you can rely on the same functionality implemented in std::stringstream class. The conversion with std::stringstream will be platform-safe and type-safe by default.

Most modern compilers will warn about the conversion and possible truncation depending on the warning level you have configured. On MSVC that is warning level 4.

Best practice would be to return a long from your function, and let the calling code decide how to handle the conversion. Barring that, at least make sure the value you get back from strtol will fit in an int before you return, as suggested by Let_Me_Be.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top