1

I am compiling a program using msvc with /NODEFAULTLIB, so I cannot use any C library functions. How do I create a C-style string (char*) containing the hex representation of a pointer (void*) like printf("%p\r\n", voidPointer) produces, so I can write it to the console using WriteConsoleW?

WriteConsoleW take in only a pointer to a buffer containing the string to output, and the number of characters in the string. How can I convert it without using a C run time library function like sprintf? However, I can use WinAPI functions, like lstrlenW, for example.

ikegami
  • 367,544
  • 15
  • 269
  • 518
Arush Agarampur
  • 1,340
  • 7
  • 20
  • Do you want it in hexadecimal? If so, do you know the algorithm? – David Schwartz Dec 20 '19 at 01:30
  • @David Schwartz Yes, I need hexadecimal. Unfortunately, I am not sure about the algorithm you are referring to. – Arush Agarampur Dec 20 '19 at 01:33
  • So you're looking for a string representation of the pointer value, as you'd get with `printf("%p", ptr)`? (As opposed to treating the `void*` as a pointer to a string?) You might want to clarify that in your question. The word "convert" can be ambiguous. – Keith Thompson Dec 20 '19 at 01:41
  • @KeithThompson Yes, you are right. I have edited my post. – Arush Agarampur Dec 20 '19 at 01:45
  • Not relevant to your question, but you don't generally need `\r\n` when writing to stdout. The implementation will convert a single `\n` character to the OS's end-of-line representation (`\n` on Unix-like systems, `\r\n` on Windows). Even less relevant for your purposes but I'll mention it anyway, hexadecimal is the most common format for `%p` but the standard doesn't specify how pointers are represented as strings. You specifically want hex, so that's not an issue. – Keith Thompson Dec 20 '19 at 01:55

3 Answers3

7

Since you say you can use the Win32 API, look at the multiple string formatting functions that the API has available:

#include <windows.h>

WCHAR buf[25];
int len = wsprintfW(buf, L"%p\r\n", voidPointer);
DWORD written;
WriteConsole(hConsole, buf, len, &written, NULL);
#include <windows.h>
#include <strsafe.h>

WCHAR buf[25];
StringCbPrintfW(buf, sizeof(buf), L"%p\r\n", voidPointer);
DWORD written;
WriteConsole(hConsole, buf, lstrlenW(buf), &written, NULL);
#include <windows.h>
#include <strsafe.h>

WCHAR buf[25], *end;
StringCbPrintfExW(buf, sizeof(buf), &end, NULL, 0, L"%p\r\n", voidPointer);
DWORD written;
WriteConsole(hConsole, buf, end-buf, &written, NULL);
#include <windows.h>
#include <strsafe.h>

WCHAR buf[25];
StringCchPrintfW(buf, sizeof(buf)/sizeof(WCHAR), L"%p\r\n", voidPointer);
DWORD written;
WriteConsole(hConsole, buf, lstrlenW(buf), &written, NULL);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    also possible use `sprintf` and `sprintf_s` from *msvcrt.dll* (which is always exist in windows) or from *ntdll.dll* (use *ntdll.lib* or *ntdllp.lib*) – RbMm Dec 20 '19 at 09:26
  • 1
    @RbMm [Does NtDll really export C runtime functions, and can I use these in my application?](https://stackoverflow.com/q/38979464/65863) – Remy Lebeau Dec 20 '19 at 16:05
6
#include <stdio.h>
#include <stdint.h>

void hexDump(void *ptr, char *buf)
{
    static char hex[16] = {
        '0', '1', '2', '3', '4',
        '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F' };
    *buf++ = '0';
    *buf++ = 'x';

    uintptr_t ip = (uintptr_t) ptr;
    for (int nibble = (2 * sizeof(ptr) - 1); nibble >= 0; --nibble)
        *buf++=hex[(ip >> (4 * nibble)) & 0xf];

    *buf = 0;
    return;        
}

int main()
{
    void *ptr = (void *) 0x1234abcd567890ef;
    char buf[20];
    hexDump(ptr, buf);
    printf("\"%s\"\n", buf);
}

Output:

"0x1234ABCD567890EF"

Here's how I would probably write the inner bit of code for real:

    // To extract the first nibble, we shift right 4 bits less
    // than the size of the pointer. Each subsequent nibble requires
    // Shifting four fewer bits. The last output requires no shift
    for (int shift = sizeof(ptr) * 8 - 4; shift >= 0; shift -= 4)
        *buf++ = hex[(((uintptr_t) ptr) >> shift) & 0xf];
David Schwartz
  • 179,497
  • 17
  • 214
  • 278
2

You can find printf-like support in the Win32 libraries without going to the C runtime. Just looking in NTDLL.DLL with depends.exe I see a pretty good selection of CRT-esque functions.

Ref: Is there a wsprintf()-type function from a low-level library such as kernel32.dll or ntdll.dll?

No need to write your own if it's already loaded into your address space :-)

screenshot of depends.exe output w/ exports from NTDLL.DLL

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • Those are unsupported private implementations. They may or may not behave like their CRT counterparts, particularly with respect to error handling and reporting. This [Q&A](https://stackoverflow.com/q/38979464/1889329) has more information, including information on other things you'd have to account for when dropping the compiler's support libraries. – IInspectable Dec 20 '19 at 13:52