13

What is the significant difference between memcpy() and strncpy()? I ask this because we can easily alter strncpy() to copy any type of data we want, not just characters, simply by casting the first two non-char* arguments to char* and altering the third argument as a multiple of the size of that non-char type. In the following program, I have successfully used that to copy part of an integer array into other, and it works as good as memcpy().

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


    int main ()
    {
    int arr[2]={20,30},brr[2]={33,44};
    //memcpy(arr,brr,sizeof(int)*1);
    strncpy((char*)arr,(char*)brr,sizeof(int)*1);
    printf("%d,%d",arr[0],arr[1]);

    }

Similarly, we can make it work for float or other data-type. So what's the significant difference from memcpy()?

PS: Also, I wonder why memcpy() is in string.h header file, given nearly all of the library functions there are related to character strings, while memcpy() is more generic in nature. Any reason?

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
Thokchom
  • 1,602
  • 3
  • 17
  • 32
  • I googled for it,but the only question that resembles it is http://stackoverflow.com/questions/4593907/difference-between-strncpy-and-memcpy ,but it doesn't answer what I intend to ask here. – Thokchom May 14 '13 at 21:37
  • memcopy copies unconditionally until it's done however many bytes you wanted. strncpy will copy until it reaches a null (string terminator), or `n` bytes copied. as such you cannot use strncpy on arbitrary binary data, because such data can natually have nulls in it. – Marc B May 14 '13 at 21:39
  • [Related question](http://stackoverflow.com/questions/6509449/is-strncpy-a-specialization-of-memcpy). – Bernhard Barker May 14 '13 at 21:40
  • Glad that I got good answers this time instead of a barrage of downvotes like my previous question!! – Thokchom May 14 '13 at 21:42

3 Answers3

24

The simple difference is that memcpy() can copy data with embedded null characters (aka the string terminator in C-style strings) whereas strncpy() will only copy the string to the maximum of either the number of characters given or the position of the first null character (and pad the rest of the strings with 0s).

In other words, they do have two very different use cases.

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
5

Take for example these numbers in your array:

 brr[2]={512,44};

The least significant byte of the first number brr[0] is 0 (512 is 0x200) which would causes 1) strncpy to stop copying. strncpy does not copy characters that follow a null character.

1) To be pedantic (see comments), this holds provided that the implementation has sizeof (int) > 1 .

ouah
  • 142,963
  • 15
  • 272
  • 331
  • What if `int` is 16 bit long and stored in big-endian order? – Kerrek SB May 14 '13 at 21:42
  • Same. The null character (although located in a different place) will stop the `strncpy` copy. – ouah May 14 '13 at 21:44
  • @KerrekSB When a person of your reputation **asks** a question,one is likely to consider it sarcasm.....but then **ouah** is no small-fish either... – Thokchom May 14 '13 at 21:50
  • @ouah I am still wondering if your answer and Kerrek's question match. – Thokchom May 14 '13 at 21:51
  • @KerrekSB Kerrek,why don't you shed some light into it? – Thokchom May 14 '13 at 21:51
  • @Thokchom: What has that to do with anything? I just wanted to clarify that the zero isn't necessarily at the beginning of the byte sequence. Moreover, the zero assumes that bytes have eight bits (but with eigh-bit bytes there will indeed be *some* zero byte somewhere, as ouah rightly points out). All told, this is a somewhat platform-dependent answer. – Kerrek SB May 14 '13 at 21:52
  • @KerrekSB Which part of the answer is platform specific? – ouah May 14 '13 at 21:53
  • @KerrekSB Shouldn't endianess be a non-issue when we are copying byte by byte? – Thokchom May 14 '13 at 21:53
  • @ouah: The claim that there's a zero. If bytes are 10 or 32 bits long, then there wouldn't be one... 32-bit long bytes are not unheard of. – Kerrek SB May 14 '13 at 21:54
  • @KerrekSB but `int` is guaranteed to be at least `16` bits. – ouah May 14 '13 at 21:54
  • 1
    @ouah: Yes, but not two bytes! – Kerrek SB May 14 '13 at 21:54
  • 1
    @Thokchom: A byte has `CHAR_BIT` bits. – Kerrek SB May 14 '13 at 21:55
  • @KerrekSB I don't want to update it in the question and lengthen it,so can you tell me this --Is the padding done with numeric 0 or the character '0'? – Thokchom May 14 '13 at 21:56
  • @KerrekSB Padding in case when the second string is smaller than NUM in `strncpy`.I tested it and it seems it gets padded with NULL terminators till NUM character condition is satisfied. – Thokchom May 14 '13 at 21:57
  • 1
    @Thokchom: Apologies, I hadn't really intended to engage with the question. I just thought this answer was a little bit iffy. (Without trying in anyway to disparage ouah's usually excellent contributions!) – Kerrek SB May 14 '13 at 21:59
  • @KerrekSB Please Kerrek,last thing,please confirm this, the padding is done with NULL characters eh?Not with the character zero right? – Thokchom May 14 '13 at 22:00
  • @KerrekSB A surprising source,the Homeland Security Site,says it gets padded with NULLs..https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/854-BSI.html BTW What has Homeland Security got to do with these stuff? – Thokchom May 14 '13 at 22:03
0

When memory block requires to be copied memcpy is useful and data in the for of string strncpy is meaningful because of the natural advantage of '\0' terminated string. Otherwise both perform same pattern of copy after execution.