2

when doing that code:

void    *ft_memcpy(void *dest, const void *src, size_t n)
{
    void    *orgdest;

    orgdest = dest;
    while (n > 0)
    {
        *(unsigned char *)dest = *(unsigned char *)src;
        n--;
        dest++;
        src++;
    }
    return (orgdest);
}

the void pointer has been typecasted to unsigned char* to copy from src to dest. Then I use the pointers inside the while loop (dest++; src++;). Should I cast them again for the arithmetics (as they were void*, and cant be used for arithmetics) like dest = ((unsigned char *)dest + 1); or are they already casted to the unsigned char type and can be used?

rpunet
  • 51
  • 4
  • Is there a specific reason why you typecasted the address in the function instead of having the input pointer in the desired type? I don't think that's a good practice to do that – Michael Teguh Laksana Jul 01 '20 at 14:04
  • its an academic exercise, required to have a prototype like this. I wonder if I have to cast it twice – rpunet Jul 01 '20 at 14:08
  • 1
    @MichaelTeguhLaksana It’s common practice to use `void*` for generic pointers. The function will obviously be called with pointers to various types, not just `unsigned char`. Using `void*` parameters means that the *caller* doesn’t have to cast. – Konrad Rudolph Jul 01 '20 at 14:08
  • Since this is a naive copy algorithm you might as well toss the whole thing out the window and write `unsigned char* d = dest; unsigned char* s = src; for(size_t i=0; i – Lundin Jul 01 '20 at 14:55
  • @KonradRudolph Ah, I see. Thanks for the information. I have never seen such thing done and I always pass the pointer with the desired type, so I'm kind of surprised with such practice. So does this mean we can put any type of variable when the function is called as an argument? – Michael Teguh Laksana Jul 01 '20 at 16:39
  • @MichaelTeguhLaksana Any type of *pointer*. And I’m sure you’ve seen this already, it’s used pervasively by the C standard library itself (`memcpy` does it, for instance) as well as operating system libraries (POSIX, Win32). – Konrad Rudolph Jul 01 '20 at 17:05

1 Answers1

2

Yes, you need to cast the pointers as arithmetic on void * pointers is illegal in C. Note that the increment is also not proper syntax, so you'd need to do

void    *ft_memcpy(void *dest, const void *src, size_t n)
{
    void    *orgdest;

    orgdest = dest;
    while (n > 0)
    {
        *(unsigned char *)dest = *(unsigned char *)src;
        n--;
        dest = ( unsigned char * ) dest + 1;
        src = ( unsigned char * ) src + 1;
    }
    return (orgdest);
}

Note that creating local copies of unsigned char * type is easier to understand:

void    *ft_memcpy(void *dest, const void *src, size_t n)
{
    const unsigned char *local_src = src;
    unsigned char *local_dest = dest;

    while (n > 0)
    {
        *local_dest = *local_src;
        n--;
        local_dest++;
        local_src++;
    }
    return (dest);
}
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • @rpunet A cast does not modify the variable you’re casting in any way. It creates a *new value* and returns that. Casting `src` does not modify `src`, and especially not *its type*: that stays `void*`, and there’s nothing you can do to change that. – Konrad Rudolph Jul 01 '20 at 14:16
  • @rpunet In your original code, the casts for the copy in `*(unsigned char *)dest = *(unsigned char *)src;` do not persist/carry over to the `dest++;` or `src++;` increment statements. – Andrew Henle Jul 01 '20 at 14:16
  • @rpunet Arithmetic on `void *` pointers is allowed as an extension by GCC, so a lot of C (and C++) programmers don't know that it's a syntax violation. – Andrew Henle Jul 01 '20 at 14:18
  • 1
    `( unsigned char * ) dest` isn't a lvalue so you can't do ++ on it. Use temporary variables as in the second example. – Lundin Jul 01 '20 at 14:52
  • 1
    @Lundin Yep. I forgot that's also a GCCism - I never do the first. [My comment on something like this was three years ago...](https://stackoverflow.com/a/44131830/4756299) – Andrew Henle Jul 01 '20 at 14:56
  • gnu11 considered harmful. – Lundin Jul 01 '20 at 14:57