6

I am trying copy an array (temp) from another array 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. But fig-1 is not working for me. Both are alomost same. But why the fig-1 is not working??

Rasmi Ranjan Nayak
  • 11,510
  • 29
  • 82
  • 122

5 Answers5

9

Because temp is not an array, it's a pointer and therefore sizeof(temp) has absolutely no relation to the array.

You want to change the memcpy to use sizeof(a). You will also want to give temp a sane value before copying to it, otherwise the program has undefined behavior.

Jon
  • 428,835
  • 81
  • 738
  • 806
5

You must allocate memory for temp with malloc() for example. For now it`s just an uninitialized pointer.

Johnny Mnemonic
  • 3,822
  • 5
  • 21
  • 33
3

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. Then you just have to replace the "3" by "ARRAY_SIZE" and it does the same job and avoid size mistakes.

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
Bastienm
  • 363
  • 2
  • 16
2

as summary of the previous answers:

you should allocate memory for tmp with size = sizeof(a). And then 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);

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
1

You can also consider an helper function.
See commit 45ccef8, commit 60566cb (25 Sep 2016) by René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit b1f0a85, 03 Oct 2016)

It uses COPY_ARRAY, a safe and convenient helper for copying arrays, complementing ALLOC_ARRAY and REALLOC_ARRAY.

So instead of memcpy(temp, a, sizeof(a));, you would use 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.

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.
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.

#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).
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

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

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.

We already have unsigned_add_overflows(), but let's add unsigned_mult_overflows() to that

/*
 * 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)

The idiom (a + b < a) works fine for detecting that an unsigned integer has overflowed, but a more explicit

unsigned_add_overflows(a, b)

might be easier to read.

Define such a macro, expanding roughly to ((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.

#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)


You can see an example with Git 2.23 (Q3 2019)

See commit 921d49b, commit 177fbab (15 Jun 2019) by René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit e8d2590, 09 Jul 2019)

use COPY_ARRAY for copying arrays

Convert calls of memcpy(3) to use COPY_ARRAY, which shortens and simplifies the code a bit.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250