1

How I can convert void * pointer to char *, so that I can print the address stored in ptr in hex format? Without printf().

#include<stdio.h>

int main()
{
    int a=5;
    void *ptr=&a;
    char *arr=(char*)ptr;
    write(1,arr,strlen(arr));

    return 0;
}

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • 2
    Why do you think you need to convert it to print? That is, is your question really "how to print a pointer value" or is it indeed "how to convert void * to char *"? And what do you mean by "without print"? – kaylum Apr 30 '20 at 08:16
  • Sorry, I think I know what you mean. By `char *` do you actually mean convert the pointer value to a string? – kaylum Apr 30 '20 at 08:21
  • Your question is not very clear. Anyway for printing anything in hexaecimal you don't need `write` which only writes raw bytes but you need `printf`. I think in your case ou just want `printf("%p\n", &a)` which prints the address of variable `a`. – Jabberwocky Apr 30 '20 at 08:21
  • @Jabberwocky For some reason OP wants it "without print". Which I guess means OP wants to manually convert the pointer to a string representation. – kaylum Apr 30 '20 at 08:22
  • If you don't want to use `printf` for whatever strange reason, you need to write your own function that converts a number to a hexadecimal string. – Jabberwocky Apr 30 '20 at 08:23
  • @kaylum maybe, I don't know what `print` is anyway. – Jabberwocky Apr 30 '20 at 08:23
  • @kaylum I wasn't aware that I can print it without converting(if it is possible). Then how I can write an address to stdout if it is stored in a void*? Something like this: write(1,ptr,...)?and about printf(), I have to imitate its behavior, so I can't use it. –  Apr 30 '20 at 08:24
  • @Nurdaulet_mit22 then you need first to write a function that converts an `int` into a hexadecimal string. – Jabberwocky Apr 30 '20 at 08:32
  • If you can use `printf %p` solution, I would recommend that. Else, (i.e. your `printf` does not support `%p`; some old versions/embedded C versions don't) you can type-cast the pointer as `int/long` and printf using `%x/%lx`. Else, function to generate `hex string` from the `int/long` can easily be hand-coded. – anishsane Apr 30 '20 at 08:32
  • @Jabberwocky, for what? isn't an address already in hex format? The thing is I am writing a function, which receives any type and prints it. –  Apr 30 '20 at 08:35
  • 2
    @Nurdaulet_mit22 computers don't store hexadecimal numbers. They just store numbers. These numbers can be represented in decimal, in hexadecimal, in octal, etc. You should probably go back to your basics. – Jabberwocky Apr 30 '20 at 08:36
  • @Jabberwocky: [Computers do not store numbers.](https://stackoverflow.com/a/60819024/298225) That would be impossible, since numbers are abstract mathematical concepts; they have no physical manifestation that could be stored in a computer. You should probably go back to your basics. – Eric Postpischil Apr 30 '20 at 10:34
  • @EricPostpischil you are right, but at the OP's level my comment is totally appropriate. – Jabberwocky Apr 30 '20 at 10:44
  • @Jabberwocky: But writing “You should probably go back to your basics” is not appropriate. It comments on the author, not the subject, and is a bit rude. The fact that a person does not have one concept quite right does not mean they have failed to learn so much that they must repeat a level of instruction. (And, while emphasizing that computers use only physical properties to store information may be more than most people wish to do, it is useful to emphasize that computers store only codes of some sort for numbers; there is nothing inherent about the bits 000101 that makes them 5.) – Eric Postpischil Apr 30 '20 at 10:57

3 Answers3

2

If you don't have printf() available, then you'll need to convert the value by hand and then write it out. The following example assumes your system is little endian (if it's big endian, just invert the for loop). See Detecting Endianness for more info.

void *ptr = &a;
unsigned char buf[sizeof(ptr)];

memcpy(buf, &ptr, sizeof(ptr));

for (int i = sizeof(ptr) - 1; i >= 0; i--) {
    unsigned char hi = (buf[i] >> 4) & 0xf; 
    unsigned char lo = buf[i] & 0xf;        
    char tmp[2] = {hi, lo};

    tmp[0] += hi < 10 ? '0' : 'a' - 10;
    tmp[1] += lo < 10 ? '0' : 'a' - 10;

    write(1, tmp, 2);
}

Result:

00007fffa6cf0f64
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • I have the same problem as the op. the twist is I am limited to 25 lines per function and can't use ternaries. I tried to convert your code but it printed as \x1f\xefO\x1f\x7fO\xaf\x7f\xdf\xaf\x0f\xdf?6of can you help me out? – Miguel M Jul 10 '21 at 20:09
  • @MiguelM I cannot help you about it in the comment section of a different answer of mine. Post a new question, if you feel like it would make a decent question. This is not a programming code-golf website though (like [Code Golf SE](https://codegolf.stackexchange.com/)), so keep that in mind. – Marco Bonelli Jul 10 '21 at 21:23
-2

The pointed to type of the pointer has nothing to do with the value pointer you want to print. If you want to print a value pointer as a number (e.g. the address at which that value is stored in& memory), you must first convert that pointer into an integer, so you can use a number printing approach. This is done inside the printf(3) function, when you specify a pointer value (no matter what type it points to) in the format, with %p format specifier.

#include<stdio.h>

int main()
{
    int a=5;

    printf("The address   of a is: %p\n", &a);
    printf("and the value of a is: %d\n", a);

    return 0;
}

On execution, you'll get something similar to this:

$ pru
The address   of a is: 0x7fffffffe3bc
and the value of a is: 5
$ _
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
-3

The function you are looking for is called sprintf. It generates the text representation (chars) of its parameters in the format you specify.

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

int main()
{
    int a = 5; // okay
    void *ptr = &a; // okay

    // conversion works only for between basic types (one number to another)
    // but not for a text (human-readable hexadecimal representation)
    //char *arr = (char*)ptr;

    // need enough memory for storing the hexadecimal text representation including 0 value at the end, we are using 20 bytes here
    char arr[20];

    // write the pointer as hexadecimal
    // depending on your architecture (32 bit / 64 bit), one of the following lines could work
    // %x writes an unsigned int, %lx an long unsigned int
    sprintf(arr, "%x", (unsigned int)ptr);        
    sprintf(arr, "%lx", (long unsigned int)ptr);

    // some systems have the secure variant sprintf_s, where you also give the length of your array arr as parameter (here: 20) to make sure it does not write over the end

    // for testing, write out the arr on screen (as %s = string)
    printf("%s\n", arr);
    //write(1,arr,strlen(arr));

    return 0;
}
Sebastian
  • 1,834
  • 2
  • 10
  • 22