[英]How to copy arrray to array using memcpy() in C
I am trying copy an array (temp)
from another array a
. 我试图复制一个数组(temp)
从另一个数组a
。 But I have it is not happening. 但我发现它并没有发生。
Fig-1
int main()
{
typedef int arr_1[3];
arr_1 arr[4];
arr_1 *temp;
arr_1 a[3] = {1, 2, 3};
memset(&temp, 0, sizeof(temp));
memcpy(temp, a, sizeof(temp));
}
But when I tried with a simple program like below, 但是当我尝试使用如下的简单程序时,
Fig-2
main()
{
int abc[3], def[3];
def[3] = {1, 2, 3};
memcpy(abc, def, sizeof(abc));
}
This above code (fig-2)
worked really fine for me. 上面的代码(fig-2)
对我来说非常好。 But fig-1
is not working for me. 但是fig-1
对我不起作用。 Both are alomost same. 两者都是相同的。 But why the fig-1
is not working?? 但为什么fig-1
不工作?
Because temp
is not an array, it's a pointer and therefore sizeof(temp)
has absolutely no relation to the array. 因为temp
不是数组,所以它是一个指针,因此sizeof(temp)
与数组完全无关。
You want to change the memcpy
to use sizeof(a)
. 您想要将memcpy
更改为使用sizeof(a)
。 You will also want to give temp
a sane value before copying to it, otherwise the program has undefined behavior. 在复制之前,您还需要给temp
一个合理的值,否则程序会有未定义的行为。
You must allocate memory for temp
with malloc()
for example. 例如,您必须使用malloc()
为temp
分配内存。 For now it`s just an uninitialized pointer. 现在它只是一个未初始化的指针。
as summary of the previous answers: 作为以前答案的摘要:
you should allocate memory for tmp
with size = sizeof(a)
. 你应该为tmp
sizeof(a)
tmp
分配内存。 And then memcpy
with size = sizeof(a)
然后memcpy
with size = sizeof(a)
arr_1 a[3] = {1, 2, 3};
arr_1 *temp = malloc(sizeof(a));
memcpy(temp, a, sizeof(a));
and do not forget to free temp
when it became useless in your program with free(temp);
当你的程序中使用free(temp);
变得无用时,别忘了释放temp
free(temp);
You can also consider an helper function. 您还可以考虑辅助函数。
See commit 45ccef8 , commit 60566cb (25 Sep 2016) by René Scharfe ( rscharfe
) . 请参阅RenéScharfe( rscharfe
)的 提交45ccef8 , 提交60566cb (2016年9月25日) 。
(Merged by Junio C Hamano -- gitster
-- in commit b1f0a85 , 03 Oct 2016) (由Junio C gitster
合并- gitster
-在提交b1f0a85 ,2016年10月3日)
It uses COPY_ARRAY
, a safe and convenient helper for copying arrays, complementing ALLOC_ARRAY
and REALLOC_ARRAY
. 它使用COPY_ARRAY
,一个安全方便的帮助程序来复制数组,补充ALLOC_ARRAY
和REALLOC_ARRAY
。
So instead of memcpy(temp, a, sizeof(a));
所以代替memcpy(temp, a, sizeof(a));
, you would use COPY_ARRAY(temp, a, 1);
,你会使用COPY_ARRAY(temp, a, 1);
Users just specify source, destination and the number of elements; 用户只需指定源,目的地和元素数量; the size of an element is inferred automatically. 自动推断元素的大小。
It checks if the multiplication of size and element count overflows. 它检查大小和元素计数的乘积是否溢出。
The inferred size is passed first tost_mult
, which allows the division there to be done at compilation time. 推断的大小首先传递给st_mult
,这允许在编译时完成分割。As a basic type safety check it makes sure the sizes of source and destination elements are the same. 作为基本类型安全检查,它确保源和目标元素的大小相同。 That's evaluated at compilation time as well. 这也是在编译时评估的。
COPY_ARRAY
is safe to use withNULL
as source pointer iff 0 elements are to be copied. 如果要复制0个元素,COPY_ARRAY
可以安全地使用NULL
作为源指针。
That convention is used in some cases for initializing arrays. 在某些情况下,该约定用于初始化数组。
Rawmemcpy(3)
does not support it -- compilers are allowed to assume that only valid pointers are passed to it and can optimize awayNULL
checks after such a call. 原始memcpy(3)
不支持它 - 允许编译器假设只有有效的指针传递给它,并且可以在这样的调用之后优化掉NULL
检查。
#define COPY_ARRAY(dst, src, n) copy_array((dst), (src), (n), sizeof(*(dst)) + \
BUILD_ASSERT_OR_ZERO(sizeof(*(dst)) == sizeof(*(src))))
static inline void copy_array(void *dst, const void *src, size_t n, size_t size)
{
if (n)
memcpy(dst, src, st_mult(size, n));
}
It uses the macro BUILD_ASSERT_OR_ZERO
which asserts a build-time dependency, as an expression (with @cond
being the compile-time condition which must be true). 它使用宏BUILD_ASSERT_OR_ZERO
来断言构建时依赖关系,作为表达式(其中@cond
是编译时条件,必须为true)。
The compilation will fail if the condition isn't true, or can't be evaluated by the compiler. 如果条件不为真,或者编译器无法评估,则编译将失败。
#define BUILD_ASSERT_OR_ZERO(cond) \
(sizeof(char [1 - 2*!(cond)]) - 1)
Example: 例:
#define foo_to_char(foo) \
((char *)(foo) \
+ BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
The inline function st_mult
is introduced in commit 320d0b4 内联函数st_mult
在commit 320d0b4中引入
static inline size_t st_mult(size_t a, size_t b)
{
if (unsigned_mult_overflows(a, b))
die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
(uintmax_t)a, (uintmax_t)b);
return a * b;
}
st_mult
is part helper functions for detecting size_t
overflow, which include unsigned_mult_overflows
st_mult
是用于检测size_t
溢出的部分辅助函数,其中包括unsigned_mult_overflows
Performing computations on
size_t
variables that we feed toxmalloc
and friends can be dangerous, as an integer overflow can cause us to allocate a much smaller chunk than we realized. 对我们提供给xmalloc
和朋友的size_t
变量执行计算可能很危险,因为整数溢出会导致我们分配比我们意识到的更小的块。We already have
unsigned_add_overflows()
, but let's addunsigned_mult_overflows()
to that 我们已经有unsigned_add_overflows()
,但是我们将unsigned_mult_overflows()
添加到
/*
* Returns true if the multiplication of "a" and "b" will
* overflow. The types of "a" and "b" must match and must be unsigned.
* Note that this macro evaluates "a" twice!
*/
#define unsigned_mult_overflows(a, b) \
((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
That uses maximum_unsigned_value_of_type
: helper for detecting unsigned overflow (from commit 1368f6 ) 它使用maximum_unsigned_value_of_type
:helper来检测无符号溢出 (来自commit 1368f6 )
The idiom
(a + b < a)
works fine for detecting that an unsigned integer has overflowed, but a more explicit 习语(a + b < a)
适用于检测无符号整数溢出,但更明确
unsigned_add_overflows(a, b)
might be easier to read. 可能更容易阅读。
Define such a macro, expanding roughly to
((a) < UINT_MAX - (b))
. 定义这样一个宏,大致扩展到((a) < UINT_MAX - (b))
。
Because the expansion uses each argument only once outside ofsizeof()
expressions, it is safe to use with arguments that have side effects. 因为扩展仅在sizeof()
表达式之外使用每个参数一次,所以可以安全地使用具有副作用的参数。
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
#define maximum_unsigned_value_of_type(a) \
(UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
with CHAR_BIT
being the number of bits in char (architecture-dependent) CHAR_BIT
是char中的位数 (取决于体系结构)
You can see an example with Git 2.23 (Q3 2019) 你可以看一下Git 2.23的例子(Q3 2019)
See commit 921d49b , commit 177fbab (15 Jun 2019) by René Scharfe ( rscharfe
) . 见RenéScharfe( rscharfe
)的 提交921d49b , 提交177fbab (2019年6月15日) 。
(Merged by Junio C Hamano -- gitster
-- in commit e8d2590 , 09 Jul 2019) (由Junio C gitster
合并- gitster
-在提交e8d2590 ,2017年7月9日)
use
COPY_ARRAY
for copying arrays 使用COPY_ARRAY
复制数组Convert calls of
memcpy(3)
to useCOPY_ARRAY
, which shortens and simplifies the code a bit. 转换memcpy(3)
调用以使用COPY_ARRAY
,这会缩短并简化代码。
I know, I'm late. 我知道,我迟到了。 But when I read the previous answers I though "you do not need all these variables" 但是,当我读到之前的答案时,我虽然“你不需要所有这些变量”
with your simple sample : 用你的简单样本:
int abc[3], def[3]; //abs is destination and def is source
def[3] = {1, 2, 3};
memcpy(abc, def, 3*sizeof(int)); //you can do sizeof(int) as you have here an array of int.
But it is better to use a variable "const int array_size = 3" or "#define ARRAY_SIZE 3" to define your array size. 但最好使用变量“const int array_size = 3”或“#define ARRAY_SIZE 3”来定义数组大小。 Then you just have to replace the "3" by "ARRAY_SIZE" and it does the same job and avoid size mistakes. 然后你只需要用“ARRAY_SIZE”替换“3”,它就可以完成同样的工作并避免出现大小错误。
With your real problem you can do : 有了你真正的问题,你可以做到:
#define ARRAY_SIZE 3
typedef int arr_1[ARRAY_SIZE];
arr_1 arr[ARRAY_SIZE+1];//it is useless here
arr_1 *temp = (arr_1 *) malloc(sizeof(arr_1)); //it is your destination, but you have a pointer of array
arr_1 a[ARRAY_SIZE] = {1, 2, 3};//it is your source
//by doing sizeof((*temp)[0])
//you do not care about the type of you array pointer
//you are sure to take the good size --> it fills your array with 0
memset((*temp), 0, (ARRAY_SIZE+1)*sizeof((*temp)[0]));
//same logic
//but you destination is (*temp) because you have a pointer of array
//it means that your array arr and a have the same type
memcpy((*temp), a, ARRAY_SIZE * sizeof(a[0]));
//by the way, the las cell of arr is still 0
//and a pointer is close to an array. If you do "tmp = a;" it works.
//but it is not a copy, you just give the a's reference to tmp
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.