0

why this code does not seem to work the way I expect

    char *c="hello";
    char *x=malloc(sizeof(char)*5+1);
    memcpy(x,(char(*)[2])c,sizeof("hello"));

    printf("%s\n",x);

On this question I got comment you cannot cast a pointer to an array. But you can cast it to a pointer to array. Try (char*[2])c so I am just casting to pointer to array of two char so it will get first two characters from c becuase this is what (char(*)[2])c suppose to do. If not then am I missing anything? and I thought since Iam copying it the at index after 1 and 2 I get junk because i did not call memset. why I am getting full hello write with memcpy even though I just casted it t0 (char(*)[2])

how to extract specific range of characters from string with casting to array type-- What it can't be done?

user786
  • 3,902
  • 4
  • 40
  • 72

1 Answers1

4

Converting a pointer does not change the memory the pointer points to. Converting the c to char [2] or char (*)[2] will not separate two characters from c.

c is char * that points to the first character of "hello".

(char (*)[2]) c says to take that address and convert it to the type “pointer to an array of 2 char”. The result points to the same address as before; it just has a different type. (There are some technical C semantic issues involved in type conversions and aliasing, but I will not discuss those in this answer.)

memcpy(x,(char(*)[2])c,sizeof("hello")); passes that address to memcpy. Due to the declaration of memcpy, that address is automatically converted to const void *. So the type is irrelevant (barring the technical issues mentioned above); whether you pass the original c or the converted (char (*)[2]) c, the result is a const void * to the same address.

sizeof "hello" is 6, because "hello" creates an array that contains six characters, including the terminating null character. So memcpy copies six bytes from "hello" into x.

Then x[5]='\0'; is redundant because the null character is already there.

To copy n characters from position p in a string, use memcpy(x, c + p, n);. In this case, you will need to manually append a null character if it is not included in the n characters. You may also need to guard against going beyond the end of the string pointed to by c.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Demo: `printf("%p %p\n", (void*)c, (void*)(char(*)[2])c);` – ikegami Nov 18 '21 at 14:07
  • thanks for answer. is it doable to implement own memcpy do I need to recompile libc? – user786 Nov 18 '21 at 14:08
  • @user786: Certainly one can implement their own `memcpy`, but it is part of standard C and is already present in the C library in normal implementations. – Eric Postpischil Nov 18 '21 at 14:12
  • If you're asking if there's a way to change the definition of `memcpy` so it works the way you expected it to (i.e. only copying two characters when the source pointer's type is `char (*)[2]`, even if the size argument is larger) then the answer is no. The C language cannot do that. (It *might* be possible in C++ with a template function but I don't know how to do it.) – zwol Nov 18 '21 at 14:17
  • I don't know why you don't just use `strncpy`. That seems to do exactly what you want, minus the syntax hacks. – paddy Nov 18 '21 at 14:23