[英]Should memcpy always be used?
I was working with C and manual memory management and playing around with my code and I noticed this: 我正在使用C和手动内存管理并玩我的代码,我注意到了这一点:
Suppose I had 假设我有
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
int c = 10;
If I take these numbers and do this: 如果我拿这些数字并执行此操作:
*a = c;
Then a
will point to a distinct location in memory separate from c
but will have the value of c
. 然后
a
将指向与c
分开的内存中的不同位置,但将具有c
的值。 If I used: 如果我用过:
memcpy(a, &c, sizeof(int));
The same thing would happen. 同样的事情会发生。 Distinct pointer, same value.
不同的指针,相同的值。
My question is whether one is preferable to the other? 我的问题是,一个人是否比另一个更好? I know for
char *
usually it is memcpy
or strcpy
that is used but what about for ints? 我知道
char *
通常是memcpy
或strcpy
使用但是对于int来说呢? What about pointers in general? 一般指针怎么样? Is assignment ever ok?
作业一切顺利吗?
PS I also know that PS我也知道
a = &c;
will make a
point to the same memory location as c
and therefore have its value but I would imagine that would leave a hanging pointer where a
was since free
is never called on the memory for a
so I wouldn't use that. 将
a
指向同一个内存位置的c
,所以有它的价值,但我猜想,会留下悬挂指针,其中a
是因为free
的内存绝不会为a
所以我不会使用。
In your example, you should use *a = c;
在您的示例中,您应该使用
*a = c;
since you only want to copy a single value. 因为你只想复制一个值。 Use
memcpy
, if you need to copy several consecutive elements of an array. 如果需要复制数组的多个连续元素,请使用
memcpy
。
It is implementation specific. 它是特定于实现的。 Some compilers, including GCC , are able to optimize quite well (with
gcc -O2
at least), calls to standard functions memcpy
and to memset
(which, as my former colleague Pascal Cuoq commented, may be inlined to efficient assignment machine code); 一些编译器,包括GCC ,能够很好地优化(至少使用
gcc -O2
),调用标准函数memcpy
和memset
(正如我以前的同事Pascal Cuoq评论的那样,可以内联到高效的赋值机器代码); sometimes, GCC is even able to optimize some assignment to some structures as calls to memcpy
(sometimes, calling an efficient memcpy
routine is faster for large enough struct
, including for structure assignment; at other occasions, the call to memcpy
, transformed via some __builtin_memcpy
, is inlined as an efficient assignment code, perhaps even going thru registers without using any memory) 有时,GCC甚至可以优化对某些结构的一些赋值,因为对
memcpy
调用(有时,对于足够大的struct
调用高效的memcpy
例程更快,包括结构赋值;在其他情况下,调用memcpy
,通过一些__builtin_memcpy
转换,内联作为一个有效的赋值代码,甚至可以通过寄存器而不使用任何内存)
You could compile your foo.c
example with gcc -fverbose-asm -O2 -march=native -S foo.c
then look into the generated foo.s
您可以使用
gcc -fverbose-asm -O2 -march=native -S foo.c
编译您的foo.c
示例,然后查看生成的foo.s
So if you use a recent GCC or Clang/LLVM compiler (or some other good compiler) with optimizations enabled , you should use memcpy
and memset
... 因此,如果您使用最近 启用了优化的 GCC或Clang / LLVM编译器(或其他一些好的编译器),您应该使用
memcpy
和memset
...
In other words, memcpy(a, &c, sizeof(int));
换句话说,
memcpy(a, &c, sizeof(int));
can be optimized as efficiently as *a = c;
可以像
*a = c;
一样有效地进行优化*a = c;
(and if you define a "type generic" macro eg using _Generic from C99, you would use memcpy
and it should be optimized efficiently). (如果您定义了“类型通用”宏,例如使用C99中的_Generic ,您将使用
memcpy
并且应该有效地优化它)。
Should memcpy always be used?
应该始终使用memcpy吗?
Plain and simple, no . 简单, 没有 。
Your first goal in writing code is to make it understandable and maintainable. 编写代码的第一个目标是使其易于理解和维护。 Everyone knows what
*a = c
will do when a
is declared as a pointer to an int and c
is declared as an int. 当
a
被声明为指向int的指针并且c
被声明为int时,每个人都知道*a = c
会做什么。 The compiler also knows exactly what you mean by that. 编译器也确切地知道你的意思。 You'll never see a compiler optimize your
*a = c
to a call to memcpy
because that would be a disoptimization. 你永远不会看到编译器优化你的
*a = c
来调用memcpy
因为那将是一种不优化。
You will see the compiler optimize *a=c
to a call to memcpy
when c
is of type struct AVeryLargeStruct
and a
is a pointer to the same. 当
c
的类型为struct AVeryLargeStruct
且a
是指向它的指针时,您将看到编译器优化*a=c
来调用memcpy
。 There's no need to convert *a=c
to memcpy(a,&c, sizeof(c))
because the compiler does that for you, a gratis . 没有必要将
*a=c
转换为memcpy(a,&c, sizeof(c))
因为编译器会为你做这件事 , 免费提供 。 Write *a=c
because that is clearer than and less error prone than is the memcpy
. 写
*a=c
因为它比memcpy
更清晰,更不容易出错。
There are a few places where you truly do need to use memcpy
(or memmove
): 有几个地方你确实需要使用
memcpy
(或memmove
):
The first is standard operating procedure; 第一是标准操作程序; no one will be shocked on reading your code and seeing a call to
memcpy
when used in that context. 在上下文中使用时,没有人会因为阅读您的代码并看到对
memcpy
的调用而感到震惊。 The latter two are not SOP. 后两者不是SOP。 Usages of
memcpy
in that context will give readers of your code pause. 在该上下文中
memcpy
用法将使读者暂停代码。 That's a good thing because you are doing something a bit tricky there. 这是一件好事,因为你在那里做了一些有点棘手的事情。 Hiding those tricky calls to
memcpy
amongst thousands of other calls to memcpy
where you could have used ordinary assignment makes those few places where you absolutely do need to use memcpy
not stand out. 隐藏那些棘手的调用
memcpy
当中成千上万的其他电话给memcpy
,你也可以使用普通的分配,使那几个地方,你绝对需要使用memcpy
不会脱颖而出。 That's a good thing only if your goal is to win the IOCCC. 只有你的目标是赢得IOCCC,这才是一件好事。
If you use memcpy
everywhere you are likely to make your code slower and you are even more likely to make others think there's something wrong with your code. 如果你在任何地方使用
memcpy
,你可能会使代码变慢,你甚至更有可能让别人认为你的代码有问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.