问题
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 bechar 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