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

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

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

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

要么

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

第二种选择总能奏效吗? 无论内容如何?

有利于最后一个的一件事是,如果arrays要改变,那么更新memcpy()会有一些内容。

谢谢

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

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

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

如果你有一个数组(真正的数组),你可以使用sizeof(array)技巧,但请注意,如果你重构代码并将其推送到数组衰减成指针的某个地方(或者如果内存最初被分配到一个指针(malloc / new),你需要传递一个已知的大小。

忽略源和目标的相对大小,也就是说,假设它们在讨论的其余部分是相同的,如果你使用C ++我会建议一个元编程技巧,它将为你提供数组的类型安全大小计数,并且将无法如果你尝试使用指针编译:

 template  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 } 

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

第二种选择总能奏效吗? 无论内容如何?

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

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

如果已使用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)); 

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

第二种选择总能奏效吗? 无论内容如何?

它只有在满足两个条件时才有效:

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

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

 uint16_t X[10]={0}; cout<<"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]))一个常量/变量,这样你就不会每次都计算..(我不知道编译器是否会一直优化这个)

这取决于。 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); } 

如果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 

怎么样?

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

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

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

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

传统上,已使用源缓冲区的大小。 有时会溢出目标缓冲区……所以最好使用一个“更安全”的函数版本:一个指定源缓冲区和目标缓冲区大小。

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

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

你不能在Linux上使用它,因为它不提供function(不要相信关于标准兼容的营销炒作))。 在Linux上,你应该“自己动手”包装。

不是每个人都喜欢更安全的function。 例如,请参阅“TR 24731’安全’function吗? 。 关于我可以说的全部内容是: 多个libunp缓冲区溢出 。 数以百万计的路由器和网关受到多个易受攻击的影响,而且许多路由器和网关仍未修补 它们是由于更安全的function会阻止的错误。 给每个说“不要使用这个微软垃圾”的人+1。