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

时间:2010-04-21 07:34:22

标签: c arrays sizeof memcpy

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

memcpy()的size参数的以下两个替代方法的优缺点是什么?

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

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

第二种选择总是有效吗?无论内容如何?

有利于最后一个的一件事是,如果阵列要改变,那么更新memcpy()将是一些管家。

由于

12 个答案:

答案 0 :(得分:27)

只要将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*)

答案 1 :(得分:5)

仅当sizeof(dst)是一个在编译时已知大小的数组时,

dst才是正确的:如int arr[ARRAY_LENGTH]或C99可变长度数组;否则它返回指针的大小,而不是目标数组的长度。

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

答案 2 :(得分: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
}

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

答案 3 :(得分:3)

  

第二种选择总是有效吗?无论内容如何?

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

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

答案 4 :(得分:2)

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

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

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

int dst2[ARRAY_LENGTH];
memcpy(dst2,src,sizeof(dst2));

答案 5 :(得分:1)

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

答案 6 :(得分:1)

  

第二种选择总是有效吗?无论内容如何?

仅在满足两个条件时才会起作用:

  • dst是常规数组,而不是指针
  • srcdst大小相同

答案 7 :(得分:1)

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

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

$> sizeof x: 20

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

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

 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]))一个常量/变量,这样你就不会每次都计算..(我不知道编译器是否会一直优化这个)

答案 8 :(得分: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);
}

答案 9 :(得分: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

答案 10 :(得分:0)

怎么样?

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

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

答案 11 :(得分:0)

  

memcpy(),size参数的值应该是什么?

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

传统上,已使用源缓冲区的大小。有时会溢出目标缓冲区......所以最好使用更安全的&#34;函数的版本:指定源缓冲区和目标缓冲区大小的版本。

你有更安全的&#34;通过ISO/IEC TR24731提供的功能。还有很多东西,比如一致的返回值和一致的字符串处理行为。

更安全&#34;函数现在是C标准的一部分,所以它应该随处可用。所以你应该使用memcpy_s

您无法在Linux上使用它,因为它不提供功能(不相信有关标准的营销宣传))。在Linux上,你应该自己推动自己的&#34;包装

并非每个人都喜欢更安全的功能。例如,请参阅Do you use the TR 24731 'safe' functions?。关于我可以说的全部内容是:Multiple libunp buffer overflows。数以百万计的路由器和网关受到多个易受攻击的影响,许多路由器和网关仍未修补。它们是由于更安全的功能会阻止的错误。每个说话的人都不会使用这个微软的错误&#34;。