英文:
What's the difference between memcpy, memmove, and strncpy for copying data in C programming?
问题
从 memcpy : abcabcde
从 strncpy : abcabcab
从 memmove : abcabcab
对于在C语言中复制数据,我建议使用memcpy
。
英文:
#include <stdio.h>
#include <string.h>
int main() {
char src[19] = "abcdef";
char *target = src;
memcpy(target+3,target,5);
printf("from memcpy : %s\n", target);
strncpy(target+3,target,5);
printf("from strncpy : %s\n", target);
memmove(target+3,target,5);
printf("from memmove : %s\n", target);
}
from memcpy : abcabcde
from strncpy : abcabcab
from memmove : abcabcab
i see different function names but the usage is the same i have searching on google microsoft some of the developers say that is it deprecated and harmeful i want to understand which one of these functions is the right for copying data in c language ?
答案1
得分: 1
Sure, here's the translation of the provided text:
简而言之:
memmove
从src
复制n
个字节到dest
。memcpy
从src
复制n
个字节到dest
,前提是这两个区域不重叠。strncpy
从src
复制n
个字节或遇到\0
字节为止,以先出现的那个为准。(前提是这两个区域不重叠。)它还使用\0
填充目标,以确保总共有n
个字符。
如果你不想考虑这些,就始终使用 memmove
。特别是(正如你可以看到,与其他函数相比,我对它的“简单”描述很长),strncpy
太奇怪和复杂,不能普遍使用。
[注:你没有提到 strlcpy
,但它非常有用,可以完成你可能希望 strncpy
完成的任务。]
为了演示 strncpy
和 memcpy
之间的区别:
char a[] = "hello";
char b[] = "world";
strncpy(a, "pqchar a[] = "hello";
char b[] = "world";
strncpy(a, "pq\0rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pq\0rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pqchar a[] = "hello";
char b[] = "world";
strncpy(a, "pq\0rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pq\0rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
这将打印:
after strncpy: a = p q = pq
after memcpy: b = p q r s = pq
请注意,memcpy
复制了所有内容,而 strncpy
仅复制了前两个字符 p
和 q
,然后将其余部分清零。
大多数情况下,源区域和目标区域不会重叠。以下是一个它们重叠的示例:
char x[] = "abcdefghi";
memmove(&x[3], &x[0], 6);
printf("after memmove: %s\n", x);
char y[] = "abcdefghi";
memcpy(&y[3], &y[0], 6);
printf("after memcpy: %s\n", y);
在我的机器上,这将打印:
after memmove: abcabcdef
after memcpy: abcabcdbc
此代码片段尝试将字符串的前 6 个字符复制到字符串的最后 6 个字符之上。使用 memmove
,这能正常工作,结果是 abcabcdef
。但是使用 memcpy
,我们得到了错误的结果,因为在它尝试复制 def
时,它们已经被 abc
覆盖了。 (实际上比这更复杂一些,但希望你能理解这个概念。)
英文:
Simply:
memmove
copiesn
bytes fromsrc
todest
.memcpy
copiesn
bytes fromsrc
todest
, as long as the two regions do not overlap.strncpy
copiesn
bytes, or up to a\0
byte, fromsrc
todest
, whichever comes first. (And as long as the two regions do not overlap.) Also it pads the destination out ton
characters using\0
, if necessary.
If you don't want to think about all this, just always use memmove
. In particular (and as you can see by the length of my "simple" description of it with respect to the others), strncpy
is too weird and complicated to be generally useful.
[Footnote: you didn't ask about strlcpy
, but it's quite useful, and does what you probably wanted strncpy
to do.]
To demonstrate the difference between strncpy
and memcpy
:
char a[] = "hello";
char b[] = "world";
strncpy(a, "pqchar a[] = "hello";
char b[] = "world";
strncpy(a, "pq\0rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pq\0rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pqchar a[] = "hello";
char b[] = "world";
strncpy(a, "pq\0rs", 5);
printf("after strncpy: a = %c %c %c %c %c = %s\n",
a[0], a[1], a[2], a[3], a[4], a);
memcpy(b, "pq\0rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
rs", 5);
printf("after memcpy: b = %c %c %c %c %c = %s\n",
b[0], b[1], b[2], b[3], b[4], b);
This prints
after strncpy: a = p q = pq
after memcpy: b = p q r s = pq
Notice that memcpy
copied everything, while strncpy
only copied the first two characters p
and q
, and then zeroed out the rest.
Most of the time, the source and destination regions do not overlap. Here's an example where they do:
char x[] = "abcdefghi";
memmove(&x[3], &x[0], 6);
printf("after memmove: %s\n", x);
char y[] = "abcdefghi";
memcpy(&y[3], &y[0], 6);
printf("after memcpy: %s\n", y);
On my machine this prints:
after memmove: abcabcdef
after memcpy: abcabcdbc
This code fragment tries to copy the first 6 characters of the string on top of the last 6 copies of the string. Using memmove
, this works, resulting in abcabcdef
. But using memcpy
, we get a wrong result, because by the time it tries to copy the def
, they have already been overwritten by abc
. (Actually it's a bit more complicated than that, but hopefully you get the idea.)
答案2
得分: 0
memcpy和memmove独立于数据类型操作,但也依赖于它。来自Linux man页面的说明:
memcpy()函数将n个字节从内存区域src复制到内存区域dest。这两个内存区域不能重叠。如果内存区域重叠,请使用memmove(3)。
为了解释我的明显矛盾:如果我有一个int2,那就是8个字节(假设我们不在一个旧的16位系统上,其中int是2个字节)。请注意,当我尝试复制1个int时会发生什么:
char hex(char num) {
if(num >= 0 && num < 10) {
return '0' + num;
} else if(num > 9 && num < 16) {
return (num - 10) + 'a';
} else {
return 'char hex(char num) {
if(num >= 0 && num < 10) {
return '0' + num;
} else if(num > 9 && num < 16) {
return (num - 10) + 'a';
} else {
return '\0';
}
}
void dump(void *ptr) {
// 假设8个字节
for(int i = 0; i<8; i++) {
char* byte = (char *) (ptr + i);
char high_nibble = (*byte & 0xf0) >> 4;
char low_nibble = *byte & 0x0f;
cout << hex(high_nibble) << hex(low_nibble) << " ";
}
cout << endl;
}
int main() {
int num[2] = {123456, 65536};
dump(&num);
memcpy(num, num + 1, 1);
dump(&num);
}
';
}
}
void dump(void *ptr) {
// 假设8个字节
for(int i = 0; i<8; i++) {
char* byte = (char *) (ptr + i);
char high_nibble = (*byte & 0xf0) >> 4;
char low_nibble = *byte & 0x0f;
cout << hex(high_nibble) << hex(low_nibble) << " ";
}
cout << endl;
}
int main() {
int num[2] = {123456, 65536};
dump(&num);
memcpy(num, num + 1, 1);
dump(&num);
}
结果是:
发生了什么?当我们将指针偏移1个位置(memcpy的第2个参数)时,它指向下一个int,但当我们指定要复制"1"时,它只复制了1个字节,而不是1个int。我们必须指定sizeof(int)作为要复制的字节数:
memcpy(num, num + 1, sizeof(int));
现在我们得到了我们需要的结果:
memcpy不允许src和dest重叠。
strncpy类似于memcpy,但用于字符串,如果在指定字节数之前遇到空字符('\0'),则复制结束。
英文:
memcpy and memmove operate dependently AND independently of data type. From the Linux man pages:
> The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas must not overlap. Use memmove(3) if the memory areas do overlap.
To address my apparent contradiction: if I have int2, that is 8 bytes (assuming we're not on an old 16-bit system where int is 2 bytes). Note what happens when I try to copy 1 int:
char hex(char num) {
if(num >=0 && num < 10) {
return '0' + num;
} else if(num > 9 && num < 16) {
return (num - 10) + 'a';
} else {
return 'char hex(char num) {
if(num >=0 && num < 10) {
return '0' + num;
} else if(num > 9 && num < 16) {
return (num - 10) + 'a';
} else {
return '\0';
}
}
void dump(void *ptr) {
// assume 8 bytes
for(int i = 0; i<8; i++) {
char* byte = (char *) (ptr + i);
char high_nibble = (*byte & 0xf0) >> 4;
char low_nibble = *byte & 0x0f;
cout << hex(high_nibble) << hex(low_nibble) << " ";
}
cout << endl;
}
int main() {
int num[2] = {123456, 65536};
dump(&num);
memcpy(num, num + 1, 1);
dump(&num);
}
';
}
}
void dump(void *ptr) {
// assume 8 bytes
for(int i = 0; i<8; i++) {
char* byte = (char *) (ptr + i);
char high_nibble = (*byte & 0xf0) >> 4;
char low_nibble = *byte & 0x0f;
cout << hex(high_nibble) << hex(low_nibble) << " ";
}
cout << endl;
}
int main() {
int num[2] = {123456, 65536};
dump(&num);
memcpy(num, num + 1, 1);
dump(&num);
}
The result is:
What happened? When we offset the pointer by 1 (2nd parameter of memcpy), it pointed to the next int, but when we specified "1" to be copied, it copied 1 byte rather than 1 int. We must specify sizeof(int) as our number of bytes to copy:
memcpy(num, num + 1, sizeof(int));
Now we get what we need:
memcpy does not allow src and dest to overlap.
strncpy is like memcpy but for strings, and if a null character ('\0') is encountered before the number of specified bytes is encountered, the copy ends.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论