简体   繁体   中英

How does memcpy work on pointers to arrays?

I initialise 2 arrays like so:

x = (double*) malloc(sizeof(double)*n);
xPlus1 = (double*) malloc(sizeof(double)*n);

Firstly, I'm not certain of exactly what x or xPlus1 now are, a pointer to an array full of doubles, or an array full of pointers to doubles? :/

The answer to that question probably effects this but if I do these various operations, I can't get it to do what I want, which is just to copy the values from xPlus1 into x. xPlus1 and x do hold different values for each index, because printing after a simple for loop achieves the desired effect:

for (int i = 0; i < n; i++) {
    x[i] = xPlus1[i];
}

But using...

memcpy(x, xPlus1, sizeof(x));
memcpy(x, &xPlus1, sizeof(x)); 

If I access x after either of these in the same function, x is unchanged, kept it's old values.

memcpy(&x, &xPlus1, sizeof(x)); 

I believe this makes x and xPlus1 point to the same memory location by the outputs I get. This is because if I modify x or xPlus1 after this copy, then both values change if I print both arrays.

memcpy(&x, xPlus1, sizeof(x)); 

Dies, exception: Unhandled exception at 0x011D5626 in MPITemplate.exe: 0xC0000005: Access violation writing location 0x00000000.

The ampersand in functions usually indicate a pass by reference, how does this play out when given to memcpy, and what difference does it make if it's going to write to the same blocks in the end?

I'd appreciate if someone could tell me in detail what's going on with these operations, because I can fiddle around making it work but I'd rather understand what's actually happening when these calls are made.

Thanks,

Mike

Both x and xPlus1 should be of type double* . They are pointers to an array of n doubles.

So when you do this:

memcpy(x, xPlus1, sizeof(x));

Since x is just a double* , that only copies sizeof(double*) bytes... which is to say, 8. What you want to do is:

memcpy(x, xPlus1, n * sizeof(*x));

because the type of *x is double , so n * sizeof(*x) will be the total bytes of memory that xPlus1 owns: n double s.

You left out the declarations.
Adding the type,

double* x = (double*) malloc(sizeof(double)*n);

makes it clearer that x is a pointer to a double .
In this particular case, the double x points to is the first element in an array of n doubles.

Something like this:

       (------- n doubles  -----)        
      ___________________________
x ===>| | | | | | | | | | | | | |
      ---------------------------

&x would give you the address of the variable x itself . This is very different from the address that the variable x contains .
(If you have int x = 1; , &x will most likely not be 1.)

memcpy takes two pointers, one for the destination and one for the source, and the size of the memory to copy.
But sizeof(x) doesn't give you the size of the array you allocated; it gives you the size of x , which is a pointer.
(Size is measured in multiples of sizeof(char) , which by definition is 1, and sizeof(double*) will be 4 (32 bits) or 8 (64 bits) on most modern machines. So you're copying 32 or 64 bits.)

The size parameter should be the same size that you passed to malloc , if you want to copy the whole thing.
The pointers should be the ones returned from malloc , since these are the memory blocks you want to copy.

So,

memcpy(x, xPlus1, sizeof(double) * n);

should work as expected.

I initialise 2 arrays like so:

No you are not. You did not show x and xPlus1 definition, but if they are arrays like:

double x[10];

your code wouldn't compile. So assuming your code compiles x and xPlus1 are pointers to double. They are close, but not the same thing.

Firstly, I'm not certain of exactly what x or xPlus1 now are, a pointer to an array full of doubles, or an array full of pointers to doubles? :/

Again you should publish their definition and then your question would not make any sense. They are pointers and whatever you assign to them does not change that fact. So they are pointers holding address of memory block size sizeof(double) * n . What will be in that memory depends on you, you can treat it as array of doubles, or something else that has size less or equal to sizeof(double) * n .

But using...

memcpy(x, xPlus1, sizeof(x));
memcpy(x, &xPlus1, sizeof(x)); 

So first line of code copies sizeof( double * ) probably 8 bytes ie one double (which is just coincedence that on 64 bit platform sizeof( double * ) == sizeof( double ) ) from memory pointed by xPlus1 to memory pointed by x . So you basically copied one element and that the same as (if you are on 32 bit platform you would just copy half of double):

x[0] = xPlus1[0]; 

Second line copied memory where pointer xPlus1 located to memory block pointed by x . So you copied double * to double x[0] which does not make much sense:

x[0] = (double) xPlus1;

This code:

memcpy(&x, &xPlus1, sizeof(x)); 

basically did this (just convoluted way):

x = xPlus1;

Following code:

memcpy(&x, xPlus1, sizeof(x)); 

is equivalent to this:

x = (double *)xPlus1[0]; 

which makes x pointer to have garbage address which leads to exception.

So your actual code should be:

memcpy( x, xPlus1, sizeof( double ) * n );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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