0

I've tried to convert an integer to a hex null-terminated (or "C-style") string but I cannot use it with printf or my custom log function. It only works if I convert it to an std::string then use .c_str() when passing it as a parameter, which produces ugly, hard-to-understand code.

It's important to know that using std::string and appending to it with "str +=" does work.

const char* IntToHexString(int nDecimalNumber) {
    int nTemp = 0;
    char szHex[128] = { 0 };
    char hex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };

    while (nDecimalNumber > 0) {
        nTemp = nDecimalNumber % 16;
        sprintf(szHex, "%s%s", hex[nTemp], szHex);

        nDecimalNumber = nDecimalNumber / 16;
    }

    sprintf(szHex, "0x%s", szHex);
    return szHex;
}

I've tried to use Visual Studio Debugger but it doesn't show any error messages, because crashes somewhere in a DLL that has no symbols loaded

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Credix
  • 3
  • 1
  • Possible duplicate of https://stackoverflow.com/questions/53853487/how-to-print-hex-value-of-an-enum-to-a-string-in-c/53855150#53855150 – andreee Jun 24 '19 at 08:51
  • `"%s%s"` should be `"%c%s"`. Also, you're returning a stack pointer, Your compiler should issue a warning for both of these. Also, I'm not sure if you can directly write from `szHex` to `szHex` in `sprintf`. Furthermore, why make the return value `const`? – Blaze Jun 24 '19 at 08:53
  • 1
    The behaviour of `sprintf` is undefined if any source string overlaps with the target. – molbdnilo Jun 24 '19 at 09:09

2 Answers2

0

Your main problem is that you define a variable on the stack, locally in the function, and then return it.

After the function returns, the char* will point to "somewhere", to an undefined position. That is a major bug. You have also other bugs that have been commented on already. Like sprintf(szHex, "0x%s", szHex);, which is undefined behaviour (UB) or sprintf(szHex, "%s%s", hex[nTemp], szHex); which has the same problem + additionally a wrong format string.

The more C++ solution would be, as already shown in many posts:

#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>

std::string toHexString(unsigned int hexValue)
{
    std::ostringstream oss;
    oss << "0x" << std::hex << hexValue;
    return std::string(oss.str());
}

int main()
{
    std::cout << toHexString(15) << '\n';
    // or directly
    std::cout << "0x" << std::hex << 15 << '\n';

    return 0;
}

Of course a C-Style solution is also possible.

But all the following I would not recommend:

If you want to stick to C like solution with char *, you could make the char szHex[128] = { 0 }; static. Or, even better, pass in the pointer to a buffer and return its address, like in

#include <stdio.h>
#include <iostream>

char* toHexCharP(unsigned int hexValue, char *outBuffer, const size_t maxSizeOutBuffer)
{
    snprintf(outBuffer,maxSizeOutBuffer-1,"0x%X",hexValue);
    return outBuffer;    
}

constexpr size_t MaxBufSize = 100U;

int main()
{
    char buf[MaxBufSize];
    std::cout << toHexCharP(15, buf, MaxBufSize) << '\n';
    return 0;
}

But as said, I would not recomend. Too dangerous.

A M
  • 14,694
  • 5
  • 19
  • 44
0

Your solution should look as follows:

std::string IntToHexString(int nDecimalNumber) {
    std::ostringstream str;
    str << std::hex << nDecimalNumber;
    return str.str();
}
// ...
std::string transformed = IntToHexString(123);

You can then use transformed.c_str() to get your string as const char*. Unless you have reasons to do so, you should never work with const char* in modern C++. Use std::string::c_str() if you need to.

andreee
  • 4,459
  • 22
  • 42