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

2
  • 5
    sizeof(temp) is the size of a pointer (to an int[3]). Commented Mar 28, 2013 at 15:05
  • @All: Johnny Mnemonic tips worked for me. I just replaced memset with temp = (arr_1*)malloc(sizeof(arr_1));. And it worked for me Commented Mar 28, 2013 at 15:14

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@AlokSave: Johnny Mnemonic tips worked for me. I just replaced memset with temp = (arr_1*)malloc(sizeof(arr_1));. And it worked for me
5

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

Comments

5

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

Comments

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

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.