c++castingcppcheck

How to fix cppcheck 'portability: Casting between unsigned char * and double * which have an incompatible binary data representation.'


I'm running CppCheck on some legacy and trying to fix all reported issues. I've got some portability warnings related to casting that I can't find how to fix.

I isolated the code in a MVCE, basically, we receive a char* (read from a USB driver). This array represents double values. To interpret them, we use a cast from char* to double*, it works well for all our supported platforms, but CppCheck does not like that.

Is there a better C++ way to to this? Or should I simply silent the warning for those lines?

void printAsDouble( char* myData, size_t size )
{
    if ( size%sizeof(double) == 0 )
    {
        double* array = (double*)myData;
        for (size_t pos = 0; pos != size/sizeof(double); ++pos)
            std::cout << "Value #" << (pos+1) << " is " << array[pos] << std::endl;
    }
}

CppCheck reports portability: Casting between char * and double * which have an incompatible binary data representation.


Solution

  • cppcheck is right to flag this code, but not for that reason. Casting from char * to double * is only safe if the char pointer is aligned for double. Otherwise you have undefined behaviour when you attempt to perform an unaligned load from the casted pointer.

    You can use memcpy instead to load the data as doubles:

    double value;
    memcpy(&value, myData + pos, sizeof(double));
    …
    pos += sizeof(double);
    

    Most compilers will optimize the memcpy into an appropriate load (or multiple loads) depending on your CPU's support for unaligned loads.