简体   繁体   English

如何使用C中的memcpy()将arrray复制到数组

[英]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_ARRAYREALLOC_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 to st_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 with NULL as source pointer iff 0 elements are to be copied. 如果要复制0个元素, COPY_ARRAY可以安全地使用NULL作为源指针。
That convention is used in some cases for initializing arrays. 在某些情况下,该约定用于初始化数组。
Raw memcpy(3) does not support it -- compilers are allowed to assume that only valid pointers are passed to it and can optimize away NULL 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_multcommit 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 to xmalloc 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 add unsigned_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 of sizeof() 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 use COPY_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM