-1

I have an exercise to do, I need to print the beginning of the address of my string, so to speak the [0] position.
I use a function that will write it in the right format 00000hexahexa, but I don't know how to send the address to the function, so it becomes a int.

Here is my code, the main function is at the bottom, size is the number of characters in the string.

I try to send the address to the function printaddr, but the compiler doesn't let me convert it to unsigned int.

void    convhexa(int nbr)
{
    char *hexa;

    hexa = "0123456789abcdef";
    if (nbr > 15)
    {
        convhexa(nbr / 16);
        convhexa(nbr % 16);
    }
    else
        write(1, &hexa[nbr], 1);
}

void    printaddr(unsigned int addr)
{
    int count;
    unsigned int nbr;

    nbr = addr;
    count = 0;
    while (nbr > 0)
    {
        nbr /= 16;
        count++;
    }
    while (count++ < 15)
        write(1, "0", 1);
    convhexa(addr);
    write(1, ": ", 2);
}

void    *ft_print_memory(void *addr, unsigned int size)
{
    char *temp;

    temp = addr;
    while (size > 0)
    {
        printaddr(temp);
        temp += 16;
        size -= 16;
    }
    return (addr);
}
GSerg
  • 76,472
  • 17
  • 159
  • 346
pikl
  • 33
  • 2
  • 7
  • Use an `uintptr_t` variable to store the address, and pass the pointer with suitable casting? – Some programmer dude Jul 31 '19 at 10:40
  • 2
    If you don't want to write your own function, you could just use `printf("%p\n", addr)`. – Steve Summit Jul 31 '19 at 10:40
  • 1
    i have to write my own fonction , it for a exercise i can only use write, thank you – pikl Jul 31 '19 at 10:42
  • 1
    i manage to make it work , i use a convertion, i send it with (unsigned int)temp and it worked thanks you all ;D – pikl Jul 31 '19 at 10:42
  • 1
    Simply use the [printf](http://www.cplusplus.com/reference/cstdio/printf/) `%p` parameter and this is it `printf("0x%p \n", str);`. In any case, any pointer is actually adderess value i.e. `unsigned long` or `unsigned long long` depending on the CPU and OS. There is a typedef type `size_t` defined by your C library which holds the exact type. So you can use `size_t address = (size_t)str;` to obtain the address value from pointer. – Victor Gubin Jul 31 '19 at 10:42
  • @VictorGubin " typedef type size_t defined by your C library which holds the exact type" --> No -`size_t` is not specified to be sufficient. Perhaps you are thinking of `uintptr_t` for object pointers? – chux - Reinstate Monica Jul 31 '19 at 10:53
  • Note: `write(1, &hexa[nbr], 1);` could be surprisingly replaced with `write(1, "0123456789abcdef" + nbr, 1);` – chux - Reinstate Monica Jul 31 '19 at 11:18
  • @chux If we check the [doc](https://en.cppreference.com/w/cpp/types/size_t) `std::size_t can safely store the value of any non-member pointer, in which case it is synonymous with std::uintptr_t. ` – Victor Gubin Jul 31 '19 at 11:37
  • @VictorGubin Note this post is tagged C. C does not defined itself in terms of C++. The quote was also couched with a restriction. "On many platforms (an exception is systems with segmented addressing) std::size_t can safely store the value of any non-member pointer, in which case it is synonymous with std::uintptr_t.", so `size_t` is not sufficient _in general_. – chux - Reinstate Monica Jul 31 '19 at 11:42

2 Answers2

2

the compiler doesn't let me convert it to unsigned int.

i manage to make it work , i use a convertion, i send it with (unsigned int)temp and it worked

Explicitly converting to an integer type is a good first step. "compiler doesn't let me convert " implies your compiler is well enabled - good.

C provides1 (u)intptr_t as an integer type sufficient to convert a void * to a integer and back to an equivalent pointer. unsigned may be too narrow and lose valuable information.

Avoid signed types in this code.
write(1, &hexa[nbr], 1); will be a problem when nbr < 0.

// void    convhexa(int nbr)
// void    printaddr(unsigned int addr)

#include <stdint.h>
void convhexa(uintptr_t nbr)
void printaddr(uintptr_t addr)

The below is precarious code. It is an infiniite loop when size is not a multiple of 16.

unsigned int size
...
while (size > 0) {
    printaddr(temp);
    temp += 16;
    size -= 16;
}

Suggest while (size >= 16)


1 These are optional types. Few modern compilers do not provide these types.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Won't be better to allow for negative values? just to define `size` as a `signed int` ??? You will need a copy of the loop body to process the remaining up to 15 bytes in case size is not a multiple of 16 (you are forgetting processing the tail block) – Luis Colorado Aug 02 '19 at 04:39
  • @LuisColorado `ft_print_memory()` is not printing the contents of memory, but a pointer value for every increment of 16. The "in between" 15 bytes are not of concern. – chux - Reinstate Monica Aug 02 '19 at 14:59
  • @LuisColorado A signed type is not required - so is not better, just trading one set of problems for another. It would have prevented the infinite loop coding trap of this learner code. Using `int` instead of `unsigned` is a problem is extreme case of `size > INT_MAX`. I would have coded `int ft_print_memory(const void *addr, size_t size)` – chux - Reinstate Monica Aug 02 '19 at 15:01
  • I know. I'm preparing some code to illustrate.... but you have to wait for it to be ready :) – Luis Colorado Aug 02 '19 at 18:22
0

to print the address, just use a %p format in your printf(3) routine. It is used with pointers, and prints the value in hexadecimal.

ssize_t print_string_with_offset(const char* s)
{
    int c;
    ssize_t res =
        printf("%08p[", s);  /* the address (w. 8 hex digits) */
    /* now print the chars of the string up (but not including) the final '\0' */
    while ((c = *s++) != 0)
        res += printf(" %02x", c & 0xff);  /* each char with 2 hex digits */
    res += printf("]\n");
    return res;
}

If you want a more elaborate hex printing routine, you can use a version write to illustrate how to print hex buffers here.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31