Converting double to hexadecimal - Code review

烈酒焚心 提交于 2019-12-24 01:02:40

问题


I have the following code that takes a double value and converts it to a hexadecimal representation, and vice versa. I would like to know whether there are any potential problems with it - whether I have overlooked something.

double hex_to_double2(string &hexString)
{
    unsigned char byte_string[sizeof(double)];
    int number;

    int j = 0;

    for(int i = 0; i < hexString.size() ; i += 2)
    {
        sscanf(&hexString[i], "%02x", &number);
        byte_string[j] = (unsigned char)number;
        ++j;
    }

    double p = (double&)byte_string;
    return p;
}

std::string double_to_hex_string(double d)
{
    unsigned char *buffer = (unsigned char*)&d;
    int bufferSize = sizeof(double);

    char converted[bufferSize * 2];

    int j = 0;
    for(int i = 0 ; i < bufferSize ; ++i)
    {
        sprintf(&converted[j*2], "%02X", buffer[i]);
        ++j;
    }
    string hex_string(converted);
    return hex_string;
}

It seems to work fine. But I have been told by someone that char converted[bufferSize * 2]; should be char converted[bufferSize * 2 + 1];

Is this the case?


回答1:


Yes, the size of converted should be bufferSize * 2 + 1. You need room for a zero or null character at the end of the string.

sprintf is inserting a null character at the end of the string, but you didn't make space for it; this means it's destroying some value in memory that comes just after the buffer. It's hard to predict what side effect this might have; it might mess up the value of some other variable, it might crash your program, or it might just appear to work fine.




回答2:


Yes. Each invocation of sprintf() will write three characters in your buffer: two hex digits and a null to terminate the string. The last of these will write one beyond the buffer as currently implemented.




回答3:


One more problem with putting a double in a char byte_string [sizeof(double)] is alignment. This rather tricky strategy is called type punning. You would want to allocate sizeof(double)*2 bytes in that function, too, and then construct an aligned pointer into the middle of the buffer.

Generally this sort of "casting about" is a bad idea, but you happen to be on the right side of the rules, almost. You just want to cast a double to a char array instead of the other way around. Also, scanf can do more work for you, and eliminate the loop.

double hex_to_double2(string &hexString)
{
    double value;

    sscanf( hexString.c_str(), "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
            (char*) & value, // note, this is a reinterpret_cast
            (char*) & value + 1,
            (char*) & value + 2,
            (char*) & value + 3,
            (char*) & value + 4,
            (char*) & value + 5,
            (char*) & value + 6,
            (char*) & value + 7 );

    return p;
}

You are only allowed to use this sort of pointer typecast from POD types (plain old data, or C-compatible) to char.

I'll leave the other way around as an exercise :) .




回答4:


This is the very simple method that I am using to convert two individual doubles with a max of 255 to hex (firstNumber and secondNumber):

std::string hexCodes = "0123456789abcdef";

std::stringstream finalResult;

finalResult << hexCodes.at(floor(firstNumber/ 16)) << hexCodes.at(firstNumber- (16 * (floor(firstNumber/ 16))));

finalResult << hexCodes.at(floor(secondNumber/ 16)) << hexCodes.at(secondNumber- (16 * (floor(secondNumber/ 16))));

std::string finalString = finalResult.str();

I am not very good at writing code and after trawling google for a result to this problem I didn't find any solutions, so wrote this and it works...so far




回答5:


Yes, character arrays (also known as C strings) should usually be terminated by '\0'. This works as a length indicator in C.

char converted[bufferSize * 2 + 1];
converted[bufferSize*2] = '\0';
or
std::memset(converted, 0, bufferSize*2+1);



回答6:


... any potential problems ...

hex_to_double2 doesn't check the string fits in your byte_string buffer: you should either check hexString.size() in advance, or add an exit condition to your for loop.

You're also returning a pointer to a local buffer, which goes out of scope when hex_to_double2 returns - don't do this. It may well deceive you by working ... until it breaks. Maybe just return std::vector<unsigned char> - that would take care of the buffer lifetime and you could fix your for loop by using push_back.

I have been told by someone that char converted[bufferSize * 2] should be char converted[bufferSize * 2 + 1]

Yes, sprintf appends a nul-terminator, so your output buffer should be bigger. But, since you're using std::string anyway, why not just format your hex digits into a std::ostringstream? Again, this will fix your buffer size issues and manage the memory for you.



来源:https://stackoverflow.com/questions/9995656/converting-double-to-hexadecimal-code-review

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!