24

我想将一个int数组复制到另一个int数组。它们对长度使用相同的定义,因此它们将始终具有相同的长度。

以下两种尺寸参数替代方案的优缺点是memcpy()什么?

memcpy(dst, src, ARRAY_LENGTH*sizeof(int));

或者

memcpy(dst, src, sizeof(dst));

第二个选项总是有效吗?不看内容?

有利于最后一个的一件事是,如果数组要更改,更新memcpy()'s.

4

12 回答 12

41

只要dst声明为具有大小的数组,sizeof就会返回该数组的大小(以字节为单位):

int dst[ARRAY_LENGTH];

memcpy( dst, src, sizeof(dst) ); // Good, sizeof(dst) returns sizeof(int) * ARRAY_LENGTH

如果dst恰好是指向此类数组的第一个元素的指针(与数组本身的类型相同),它将不起作用:

int buffer[ARRAY_LENGTH];
int* dst = &buffer[0];

memcpy( dst, src, sizeof(dst) ); // Bad, sizeof(dst) returns sizeof(int*)
于 2010-04-21T07:39:40.810 回答
5

sizeof(dst)仅当dst是一个在编译时大小已知的数组时才是正确的:例如int arr[ARRAY_LENGTH]或 C99 可变长度数组;否则它返回指针的大小,而不是目标数组的长度。

为避免将来出现错误,请保持一致并首选第一种形式:类型的大小 * 长度。

于 2010-04-21T07:36:32.000 回答
5

如果您使用 malloc 进行分配,则必须说明数组的大小

int * src = malloc(ARRAY_LENGTH*sizeof(*src));
int * dst1 = malloc(ARRAY_LENGTH*sizeof(*dst1));
memcpy(dst1,src,ARRAY_LENGTH*sizeof(*dst1));

如果您分配了静态数组,则可以使用sizeof

int dst2[ARRAY_LENGTH];
memcpy(dst2,src,sizeof(dst2));
于 2010-04-21T07:39:01.870 回答
5

如果并且当您有一个数组(真实的)时,您可以使用该sizeof(array)技巧,但请注意,如果您重构代码并将其推送到数组已衰减为指针的位置(或者如果内存最初是在指针中分配的(malloc /new) 你需要传递一个已知的大小。

忽略源和目标的相对大小,也就是说,假设它们在讨论的其余部分是相同的,如果你使用 C++,我会推荐一个元编程技巧,它会给你一个类型安全的数组大小计数,并且会失败如果您尝试将其与指针一起使用,请编译:

template <typename T, int N>
inline int array_memory_size( T (&a)[N] ) { return sizeof a; }

那样:

int main() {
   int array[10];
   int *ptr = array;
   int orig[10] = { 0 };
   memcpy( array, orig, array_memory_size(array) ); // ok
   //memcpy( ptr, orig, array_memory_size(ptr) ); // compilation error
}

如果您在任何时候重构并且代码移动到数组已衰减的位置(或者您将静态数组替换为动态分配的数组),编译器会告诉您需要更正大小计算。

于 2010-04-21T07:47:38.860 回答
3

第二个选项总是有效吗?不看内容?

第二个选项仅在您添加回缺少的) 并且 dst是静态数组(即 type int[123])时才有效。

如果dst具有未知大小(即int[]),则sizeof dst仅返回指针大小,因为dst已衰减为指针。在这种情况下,您需要使用sizeof(*dst)*ARRAY_LENGTH.

于 2010-04-21T07:39:28.530 回答
1

假设 dst 是 int* 类型,sizeof(dst) 将返回指针本身的大小(即 4 在 32 位系统上,8 在 64 位系统上),所以你的第二个例子只会复制这么多字节,而第一个将正确使用内容的实际大小。

于 2010-04-21T07:38:07.620 回答
1

第二个选项总是有效吗?不看内容?

只有同时满足两个条件才会起作用:

  • dst是常规数组,而不是指针
  • src并且dst大小相同
于 2010-04-21T07:40:57.670 回答
1

如果 X 是 10 的 uint16_t 数组,sizeof(X) 总是给你“X”的字节数,然后 sizeof(X) 将返回 20

uint16_t X[10]={0};
cout<<"sizeof x: "<<sizeof(X);

$> sizeof x: 20

如果你想要元素的数量,你必须做一些字节算术:
8bit = 1byte
16bit = 2bytes
32bit = 4 bytes
64bit = 8 bytes

所以要获得你可以做的元素数量:

 numb_of_elements = ( sizeof(X)/sizeof(X[0]) );

导致:

uint32_t source[100]={0};
memcpy((void*) dest, (void*) source, ( sizeof(source)/sizeof(source[0]) ));

当然,您可能希望将( sizeof(X)/sizeof(X[0]) )设为常量/变量,这样您就不会每次都进行计算。(我不知道编译器是否会始终对此进行优化)

于 2013-03-08T18:30:16.353 回答
1

memcpy(),size参数的值应该是多少?

它应该是源缓冲区大小和目标缓冲区大小之间的最小值。

传统上,一直使用源缓冲区的大小。有时会溢出目标缓冲区......因此最好使用该函数的“更安全”版本:指定源缓冲区和目标缓冲区大小的函数。

您可以通过ISO/IEC TR24731获得“更安全”的功能。它还有很多,比如一致的返回值和一致的字符串处理行为。

“更安全”的功能现在是 C 标准的一部分,因此它应该随处可用。所以你应该使用memcpy_s.

你不能在 Linux 上使用它,因为它不提供这些功能(不要相信关于符合标准的营销炒作))。在 Linux 上,您应该“滚动自己的”包装器。

Not everyone is a fan of the safer functions. See, for example, Do you use the TR 24731 'safe' functions?. About all I can say about that is: Multiple libunp buffer overflows. Millions of routers and gateways are subject to multiple vulnerable and many remain unpatched. And they were due to bugs that would have been stopped by the safer functions. +1 to everyone who is saying "don't use this Microsoft crap".

于 2014-11-20T01:01:03.810 回答
0

这取决于。arr 和 pointer 都是数组,但 sizeof() 只返回正确的 arr 大小,这是在编译时声明的。

int main() {
        int arr[10];
        int * pointer;
        pointer = (int *) malloc(10 * sizeof(int));
        printf("%d\n", sizeof(arr)); // 40
        printf("%d\n", sizeof(pointer)); // 4 or 8
        free(pointer);
}
于 2010-04-21T07:41:53.150 回答
0

如果 dst 是从堆中分配的(例如使用 malloc),则第二种解决方案将不起作用。sizeof(dst) 只有在编译器知道时才会起作用。例如,以下示例将失败,因为 sizeof(dst) 将等于指针的大小(4-8 字节)。

#define ARRAY_LENGTH 10
int *dst;

dst = malloc(ARRAY_LENGTH*sizeof(int));
memcpy(dst, src, sizeof(dst)); // sizeof dst in this case would be 4 bytes on 32 bit system

此代码段每次都会起作用:

#define ARRAY_LENGTH 10
int *dst;

dst = malloc(ARRAY_LENGTH*sizeof(int));
memcpy(dst, src, ARRAY_LENGTH*sizeof(int)); // sizeof would be 40 bytes
于 2010-04-21T07:46:10.193 回答
-1

怎么样?

memcpy(dst, src, &src[ARRAY_LENGTH] - &src[0]);

即使单个元素的大小小于实际数组中每个项目的大小,这也应该有效。

于 2010-04-21T07:55:22.937 回答