英文:
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:
memmovecopiesnbytes fromsrctodest.memcpycopiesnbytes fromsrctodest, as long as the two regions do not overlap.strncpycopiesnbytes, or up to a\0byte, fromsrctodest, whichever comes first. (And as long as the two regions do not overlap.) Also it pads the destination out toncharacters 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。




评论