Search code examples
c++gcccharconstantsfreestanding

uintx_t to const char* in freestanding c++ using GNU compiler


so I am trying to convert some integers in to character arrays that my terminal can write. so I can see the value of my codes calculations for debugging purposes when its running. as in if the int_t count = 57 I want the terminal to write 57. so char* would be an array of character of 5 and 7

The kicker here though is that this is in an freestanding environment so that means no standard c++ library. EDIT: this means No std::string, no c_str, no _tostring, I cant just print integers.

The headers I have access to are iso646,stddef,float,limits,stdint,stdalign, stdarg, stdbool and stdnoreturn

Ive tried a few things from casting the int as an const char*, witch just led to random characters being displayed. To feeding my compiler different headers from the GCC collection but they just keeped needing other headers that I continued feeding it until I did not know what header the compiler wanted.

so here is where the code needs to be used to be printed.

uint8_t count = 0;
while (true)
{
    terminal_setcolor(3);
    terminal_writestring("hello\n");

    count++;

    terminal_writestring((const char*)count);
    terminal_writestring("\n");
}

any advice with this would be greatly appreciated.

I am using an gnu, g++ cross compiler targeted at 686-elf and I guess I am using C++11 since I have access to stdnoreturn.h but it could be C++14 since I only just built the compiler with the latest gnu software dependencies.


Solution

  • Without C/C++ Standard Library you have no options except writing conversion function manually, e.g.:

    template <int N>
    const char* uint_to_string(
        unsigned int val,
        char (&str)[N],
        unsigned int base = 10)
    {
        static_assert(N > 1, "Buffer too small");
        static const char* const digits = "0123456789ABCDEF";
    
        if (base < 2 || base > 16) return nullptr;
    
        int i = N - 1;
        str[i] = 0;
    
        do
        {
            --i;
            str[i] = digits[val % base];
            val /= base;
        }
        while (val != 0 && i > 0);
    
        return val == 0 ? str + i : nullptr;
    }
    
    template <int N>
    const char* int_to_string(
        int val,
        char (&str)[N],
        unsigned int base = 10)
    {
        // Output as unsigned.
        if (val >= 0) return uint_to_string(val, str, base);
    
        // Output as binary representation if base is not decimal.
        if (base != 10) return uint_to_string(val, str, base);
    
        // Output signed decimal representation.
        const char* res = uint_to_string(-val, str, base);
    
        // Buffer has place for minus sign
        if (res > str) 
        {
            const auto i = res - str - 1;
            str[i] = '-';
            return str + i;
        }
        else return nullptr;
    }
    

    Usage:

    char buf[100];
    terminal_writestring(int_to_string(42, buf));      // Will print '42'
    terminal_writestring(int_to_string(42, buf, 2));   // Will print '101010'
    terminal_writestring(int_to_string(42, buf, 8));   // Will print '52'
    terminal_writestring(int_to_string(42, buf, 16));  // Will print '2A'
    terminal_writestring(int_to_string(-42, buf));     // Will print '-42'
    terminal_writestring(int_to_string(-42, buf, 2));  // Will print '11111111111111111111111111010110'
    terminal_writestring(int_to_string(-42, buf, 8));  // Will print '37777777726'
    terminal_writestring(int_to_string(-42, buf, 16)); // Will print 'FFFFFFD6'
    

    Live example: http://cpp.sh/5ras