3

strncpy() and memcpy() are the same?

Because of the fact that strncpy() only accepts char * as parameter, Icasts the integer arrays to char *.

Why it gets the different output?

Here is My code,

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#define SIZE 5


void print_array(int *array, char *name ,int len) {
    int i;
    printf("%s ={ ",name);
    for(i=0; i<len;i++)
        printf("%d," ,array[i]);
    printf("}\n");
}

int main(void){
    char string1[SIZE] = {'1','2','3','4','\0'};
    char string2[SIZE], string3[SIZE];
    int array1[SIZE] = {1,2,3,4,5};
    int array2[SIZE],array3[SIZE];

    strncpy(string2,string1,sizeof(string1));
    memcpy(string3, string1,sizeof(string1));
    printf("string2 =%s \n",string2);
    printf("string3 =%s \n",string3);

    strncpy((char *)array2, (char*)array1 , sizeof(array1));
    memcpy(array3,array1,sizeof(array1));
    print_array(array2,"array2",SIZE);
    print_array(array3,"array3",SIZE);

    return 0;
}

It turns out

string2 =1234
string3 =1234
array2 ={ 1,0,0,0,0,}
array3 ={ 1,2,3,4,5,}

But Why? It gives different answer?

C learner
  • 53
  • 2
  • 9

2 Answers2

12
strncpy((char *)array2, (char*)array1 , sizeof(array1));

Casting array1 to a char * doesn't do what you want. There are no characters at that location, there are only integers (little-endian it seems).

What is happening is that strncpy copies bytes from the integer array until it reaches a 0 byte, which is pretty soon. On the other hand memcpy doesn't care about 0 bytes and just copies the whole thing.

To put it another way, strncpy finds a 0 byte "inside" the first integer and stops copying; it does however fill the destination buffer with zeros up to the specified size.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • The `strncpy()` stops on the 2nd byte because the integer 1 (as bytes) is 0x01,0x00,0x00,0x00 (x86 is little endian). This is easily verified. – Emmet Sep 03 '13 at 17:33
  • `strncpy` doesn't really "stop" at zero character. It stops reading the source data, but it does not stop writing to the destination buffer. The rest of the destination buffer is filled with zeroes. – AnT stands with Russia Sep 03 '13 at 18:12
1

You can implement (sort of) strncpy with memcpy, but the other way around won't work, because strncpy stops at the "end of the string", which doesn't work at all well for data that isn't a C style string (e.g. has zero bytes in it).

To write strncpy with memcpy would be something like this:

char *strncpy(char *dest, const char *src, size_t maxlen)
{
   size_t len = strlen(src);
   memcpy(dest, src, min(len, maxlen));
   if (len < maxlen) memset(dest+len, 0, maxlen-len);
   return dest;
}

(Note: The above implementation doesn't work for the case where the src string is not terminated correctly - a real strncpy does cope with this - it could be fixed in the above code, but it gets quite complicated).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Note that this would be a poor-quality implementation because it has to process the string twice. Also, you **can** implement `memcpy` with `strncpy`; it would just have to restart every time it hits a zero byte, which would be very inefficient, especially in the degenerate case where the source is all zeros. – R.. GitHub STOP HELPING ICE Sep 03 '13 at 17:22
  • @R.. Right, agree on the poor implementatin. But in the second case, I can't see how you could do that in any way that doesn't either work over the data many times, and essentially just using `strncpy` to copy one or a few bytes at a time. A bit like using a plastic spoon to dig a fish-pond in the garden. Given enough time, it's possible, but it's very inefficient and tedious work. – Mats Petersson Sep 03 '13 at 17:32
  • @Mats Petersson: That implementation does not simulate standard `strncpy` at all. `strncpy` is not a limited-length string copying function. `strncpy` is a conversion function that converts zero-terminated strings into fixed-width strings. Its critically important feature is the fact that it fills the tail portion of the target buffer with zeros. Your version does not do it, i.e. what you implemented is not `strncpy`. – AnT stands with Russia Sep 03 '13 at 18:00
  • @AndreyT: Ok, I must admit I've NEVER (at least as I can recall - it sometimes gets blurry what you have or haven't done when you've been working for 25 years or more) used `strncpy` to copy a string that isn't correctly terminated [it may well be terminated well after the position where I stop copying, which is a different matter]. I think I've fixed your main point, but not the "could be that the input is not zero terminated". It was not meant as "This is a proper implementation", but rather to show the relationship. – Mats Petersson Sep 03 '13 at 18:11