Also there is a thing that you might want to notice - it doesn't matter if it is like this

int *p =&matrix1[0][0];
int *q =&matrix2[0][0];
memcpy(p, q, 13*15*sizeof(*p));

Sure you can do this also,

memcpy(&matrix2[0][0], &matrix1[0][0], 13*15*sizeof(matrix1[0][0]));

void *memcpy(void * restrict s1,
             const void * restrict s2,
             size_t n);

Why this works? Because memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. Well this basically sums up every thing you need to use memcpy. So what happens if it is a pointer - the strategy will be same. Pointer point to source and target and they don't overlap - and you then mention the bytes. Voila - it would copy.

Another thing to note - you can get these values 13 and 15 using sizeof operator.

size_t rows = sizeof matrix1 / sizeof matrix1[0];
size_t cols = sizeof matrix1[0] / sizeof matrix1[0][0];

memcpy(&matrix2[0][0], &matrix1[0][0], rows*cols*sizeof(matrix1[0][0]));

And also even more clearly (lurker suggested) :-

memcpy(&matrix2[0][0], &matrix1[0][0], sizeof matrix1);

And these would also work (It was chux who mentioned this)

memcpy(matrix2, matrix1, sizeof matrix2);

Because they all have same value - pointing to same address but their type is different which anyway doesn't matter here because it is converted to void*.


An even better solution which would work whether these variables denotes array or struct or some scalar variable is (suggested by chux )

memcpy(&matrix2, &matrix1, sizeof matrix2);
Answer from user2736738 on Stack Overflow
Top answer
1 of 1
6

Also there is a thing that you might want to notice - it doesn't matter if it is like this

int *p =&matrix1[0][0];
int *q =&matrix2[0][0];
memcpy(p, q, 13*15*sizeof(*p));

Sure you can do this also,

memcpy(&matrix2[0][0], &matrix1[0][0], 13*15*sizeof(matrix1[0][0]));

void *memcpy(void * restrict s1,
             const void * restrict s2,
             size_t n);

Why this works? Because memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. Well this basically sums up every thing you need to use memcpy. So what happens if it is a pointer - the strategy will be same. Pointer point to source and target and they don't overlap - and you then mention the bytes. Voila - it would copy.

Another thing to note - you can get these values 13 and 15 using sizeof operator.

size_t rows = sizeof matrix1 / sizeof matrix1[0];
size_t cols = sizeof matrix1[0] / sizeof matrix1[0][0];

memcpy(&matrix2[0][0], &matrix1[0][0], rows*cols*sizeof(matrix1[0][0]));

And also even more clearly (lurker suggested) :-

memcpy(&matrix2[0][0], &matrix1[0][0], sizeof matrix1);

And these would also work (It was chux who mentioned this)

memcpy(matrix2, matrix1, sizeof matrix2);

Because they all have same value - pointing to same address but their type is different which anyway doesn't matter here because it is converted to void*.


An even better solution which would work whether these variables denotes array or struct or some scalar variable is (suggested by chux )

memcpy(&matrix2, &matrix1, sizeof matrix2);
🌐
GitHub
gist.github.com › 940849ed3e0fcaebee54
memcpy and two-dimensional array · GitHub
memcpy and two-dimensional array · Raw · main.c · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Discussions

Copy 2D array to another 2D array. - C++ Forum
Copy 2D array to another 2D array. More on cplusplus.com
🌐 cplusplus.com
September 29, 2019
How to clone multidimensional array to another array Arduino
Hello everyone 🙂 , I’m working with a multidimensional array [4][8] FourRowsEightColums and I have been trying to copy all values array to another array[4][8] with the exactly the same structure FourRowsEightColums. char ArrayA[4][8] ={ {'H','-','L','-','H','-','L','-'}, {'-','H','-',... More on forum.arduino.cc
🌐 forum.arduino.cc
0
0
March 16, 2020
How to memcpy a part of a two dimensional array in C? - Stack Overflow
There's no way for memcpy() to know about the in-memory layout of a and "respect" it, it will overwrite sizeof c adjacent bytes which might not be what you mean. More on stackoverflow.com
🌐 stackoverflow.com
c++ - Is copying 2D arrays with "memcpy" technically undefined behaviour? - Stack Overflow
An interesting discussion has arisen in the comments to this recent question: Now, although the language there is C, the discussion has drifted to what the C++ Standard specifies, in terms of what More on stackoverflow.com
🌐 stackoverflow.com
September 25, 2021
🌐
NVIDIA Developer Forums
forums.developer.nvidia.com › accelerated computing › cuda › cuda programming and performance
2D array with memcopy2D and Kernel usage - CUDA Programming and Performance - NVIDIA Developer Forums
January 18, 2016 - Hi, I am trying to build a kernel that employs 2D array to to implement a function. I have one constraint that the array should be used in a[i][j] form in kernel for sake of code reusability. Here what i tried with sim…
🌐
Cplusplus
cplusplus.com › forum › general › 263317
Copy 2D array to another 2D array. - C++ Forum
September 29, 2019 - Hello. Asking for help about copying 2D arrays. For example : I have an array - float a[50][50]. Users input numbers themselves.
🌐
rohitab.com
rohitab.com › discuss › topic › 38972-copying-a-2d-array-with-memcpy
Copying a 2d array with memcpy - Programming - rohitab.com - Forums
May 25, 2025 - Copying a 2d array with memcpy - posted in Programming: memset(board_cpy, 0, sizeof(board[0][0])*rows*cols); memcpy(board_cpy, board, sizeof(board[0][0])*rows*cols);Trying to copy a 2d array but i get the following warningboard_cpy' may be used uninitialized in this function|What is it expecting me to do?
🌐
Arduino Forum
forum.arduino.cc › projects › programming
How to clone multidimensional array to another array Arduino - Programming - Arduino Forum
March 16, 2020 - Hello everyone 🙂 , I’m working with a multidimensional array [4][8] FourRowsEightColums and I have been trying to copy all values array to another array[4][8] with the exactly the same structure FourRowsEightColums. char ArrayA[4][8] ={ {'H','-','L','-','H','-','L','-'}, {'-','H','-',...
Top answer
1 of 8
30

std::memcpy(arr_copy, arr, sizeof arr); (your example) is well-defined.

std::memcpy(arr_copy, arr[0], sizeof arr);, on the other hand, causes undefined behavior (at least in C++; not entirely sure about C).


Multidimensional arrays are 1D arrays of arrays. As far as I know, they don't get much (if any) special treatment compared to true 1D arrays (i.e. arrays with elements of non-array type).

Consider an example with a 1D array:

int a[3] = {1,2,3}, b[3];
std::memcpy(b, a, sizeof(int) * 3);

This is obviously legal.1

Notice that memcpy receives a pointer to the first element of the array, and can access other elements.

The element type doesn't affect the validity of this example. If you use a 2D array, the element type becomes int[N] rather than int, but the validity is not affected.

Now, consider a different example:

int a[2][2] = {{1,2},{3,4}}, b[4];
std::memcpy(b, a[0], sizeof(int) * 4);
//             ^~~~

This one causes UB2, because since memcpy is given a pointer to the first element of a[0], it can only access the elements of a[0] (a[0][i]), and not a[j][i].

But, if you want my opinion, this is a "tame" kind of UB, likely to not cause problems in practice (but, as always, UB should be avoided if possible).



1 The C++ standard doesn't explain memcpy, and instead refers to the C standard. The C standard uses somewhat sloppy wording:

C11 (N1570) [7.24.2.1]/2

The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1.

A pointer to the first (or any) element of an array points only to that element, not to the entire array, even though the entire array is reachable through said pointer. Thus, if interpreted literally, it appears that @LanguageLawyer is right: if you give memcpy a pointer to an array element, you're only allowed to copy that single element, and not the successive elements.

This interpretation contradicts the common sense, and most probably wasn't intended.

E.g. consider the example in [basic.types.general]/2, which applies memcpy to an array using a pointer to the first element: (even though examples are non-normative)

constexpr std::size_t N = sizeof(T);
char buf[N];
T obj;
std::memcpy(buf, &obj, N);
std::memcpy(&obj, buf, N);

2 This is moot, because of the problematic wording for memcpy described above.

I'm not entirely sure about C, but for C++, there are strong hints that this is UB.

Firstly, consider a similar example that uses std::copy_n, attempting to perform an element-wise copy rather than a byte-wise one:

#include <algorithm>

consteval void foo()
{
    int a[2][2] = {{1,2},{3,4}}, b[2][2] = {{1,2},{3,4}};
    std::copy_n(a[0], 4, b[0]);
}

int main() {foo();} 

Running functions at compile-time catches most form of UB (it makes the code ill-formed), and indeed compiling this snippet gives:

error: call to consteval function 'foo' is not a constant expression
note: cannot refer to element 4 of array of 2 elements in a constant expression

The situation with memcpy is less certain, because it performs a byte-wise copy. This whole topic seems appears to be vague and underspecified.

Consider the wording for std::launder:

[ptr.launder]/4

A byte of storage b is reachable through a pointer value that points to an object Y if there is an object Z, pointer-interconvertible with Y, such that b is within the storage occupied by Z, or the immediately-enclosing array object if Z is an array element.

In other words, given a pointer to an array element, all elements of the said array are reachable through that pointer (non-recursively, i.e. through &a[0][0] only a[0][i] are reachable).

Formally, this definition is only used to describe std::launder (the fact that it can't expand the reachable region of the pointer given to it). But the implication seems to be that this definition summarizes reachability rules described by other parts of the standard ([static.cast]/13, notice that reinterpret_cast is defined through the same wording; also [basic.compound]/4).

It's not entirely clear if said rules apply to memcpy, but they should. Because otherwise, the programmer would be able to disregard reachability using library functions, which would make the concept of reachability mostly useless.

2 of 8
18

It's well-defined, even if you use memcpy(arr_cpy, arr, size) rather than
memcpy(&arr_cpy, &arr, size) (which @LanguageLawyer has finally explained is what they've been arguing for the whole time), for reasons explained by @HolyBlackCat and others.

The intended meaning of the standard is clear, and any language to the contrary is a defect in the standard, not something compiler devs are going to use to pull the rug out from under countless normal uses of memcpy (including 1D arrays) that don't cast int* to int (*)[N], especially since ISO C++ doesn't allow variable-length arrays.

Experimental evidence for how compiler-developers chose to interpret the standard as letting memcpy read from the whole outer object (array-of-array-of-int) which is pointed-to by the void* arg, even if that void* was obtained as a pointer to the first element (i.e. to the first array-of-int):

If you pass a size that's too large, you do get a warning, and for GCC the warning even spells out exactly what object and what size it sees being memcpyed:

#include <cstring>

int dst[2][2];
void foo(){
    int arr[2][2] = {{1,1},{1,1}};
    std::memcpy(dst, arr, sizeof(arr));  // compiles cleanly
}

void size_too_large(){
    int arr[2][2] = {{1,1},{1,1}};
    std::memcpy(dst, arr, sizeof(arr)+4);
}

Using &dst, &src makes no difference here to warnings or lack thereof.
Godbolt compiler explorer for GCC and clang -O2 -Wall -Wextra -pedantic -fsanitize=undefined, and MSVC -Wall.

GCC's warning for size_too_large() is:

warning: 'void* memcpy(void*, const void*, size_t)' forming offset [16, 19] is  \
  out of the bounds [0, 16] of object 'dst' with type 'int [2][2]' [-Warray-bounds]
   11 |     std::memcpy(dst, arr, sizeof(arr)+4);
      |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
<source>:3:5: note: 'dst' declared here
    3 | int dst[2][2];

clang's doesn't spell out the object type, but does still show sizes:

<source>:11:5: warning: 'memcpy' will always overflow; destination buffer has size 16, but size argument is 20 [-Wfortify-source]
    std::memcpy(dst, arr, sizeof(arr)+4);
    ^

So it's clearly safe in practice with real compilers, a fact which we already knew. Both see the destination arg as being the whole 16-byte int [2][2] object.

However, GCC and clang are possibly less strict than the ISO C++ standard. Even with dst[0] as the destination (decaying to an int* rather than int (*)[2]), they both still report the destination size as 16 bytes with type int [2][2].

HolyBlackCat's answer points out that calling memcpy this way really only gives it the 2-element sub-array, not the whole 2D array, but compilers don't try to stop you from or warn about using a pointer to the first element to access any part of a larger object.

As I said, testing real compilers can only show us that this is well-defined on them currently; arguments about what they might do in future requires other reasoning (based on nobody wanting to break normal uses of memcpy, and the standard's intended meaning.)


ISO standard's exact wording: arguably a defect

The only question is whether there's any merit to the argument that there's a defect in the standard's wording for the way it explains which object is relevant for the language beyond the end of an object, whether that's limited to the single pointed-to object after array to pointer "decay" for passing an arg to memcpy. (And yes, that would be a defect in the standard; it's widely assumed that you don't need and shouldn't use &arr with an array type for memcpy, or basically ever AFAIK.)

To me, that sounds like a misinterpretation of the standard, but I may be biased because I of course want to read it as saying what we all know is true in practice. I still think that having it be well-defined is a valid interpretation of the wording in the standard, but the other interpretation may also be valid. (i.e. it could be ambiguous whether it's UB or not, which would be a defect.)

A void* pointing to the first element of an array can be cast back to an int (*)[2] to access the whole array object. That isn't how memcpy uses it, but it shows that the pointer hasn't lost its status as a pointer to the whole N-dimensional array. I think the authors of the standard are assuming this reasoning, that this void* can be considered a pointer to the whole object, not just the first element.

However, it's true that there's special language for how memcpy works, and a formal reading could argue that this doesn't let you rely on normal C assumptions about how memory works.

But the UB interpretation allowed by the standard is not how anyone wants it to work or thinks it should. And it would apply to 1D arrays, so this interpretation conflicts with standard examples of using memcpy that are well-known / universally assumed to work. So any argument that the wording in the standard doesn't quite match this is an argument that there's a defect in the wording, not that we need to change our code and avoid this.

There's also no motivation for compiler devs to try to declare this UB because there's very little optimization to be had here (unlike with signed overflow, type-based aliasing, or assumption of no NULL deref).

A compiler assuming that runtime-variable size must only affect at most the whole first element for the pointer type that got cast to void* wouldn't allow much optimization in real code. It's rare for later code to only access elements strictly after the first, which would let the compiler do constant-propagation or similar things past a memcpy that was intended to write it.

(As I said, everyone knows this isn't what the standard intended, unlike with clear statements about signed overflow being UB.)

Find elsewhere
🌐
Cprogramming
cboard.cprogramming.com › c-programming › 148686-copying-2d-array-into-another-2d-array.html
copying a 2D array into another 2D array
Well the first thing to do is to make sure your dest array is at least as big as your source array. For this, you will need something like int dest_array[20][4]; The memcpy would work, but you need to copy min(sizeof(dest_array),sizeof(array)), where both arrays are in scope.
🌐
Stack Overflow
stackoverflow.com › questions › 60541948 › copy-2d-array-to-new-buffer-with-memcpy
c - Copy 2D array to new buffer with memcpy - Stack Overflow
March 5, 2020 - myBuffered_Aray[100][7]; uint8 *pValues; Get_2D_Array(&pValues) { for (uint8 i = 0; i < 100; i++) { for (uint8 j = 0; j < 7; j++) { (void)memcpy(myBuffered_Aray[i][j], (u8_t*)&pValues[i][j], sizeof(uint8)); } }
🌐
Stack Overflow
stackoverflow.com › questions › 33172715 › memcpy-and-two-dimensial-arrays
c - Memcpy and two-dimensial arrays - Stack Overflow
void Copy(double **mt, int sx, int ex, int sy, int ey, double **res) { int i; int t = sizeof(double)*(ey-sy+1); for(i = 0; i < ex-sx+1; i++) memcpy(&mt[i][0],&res[sx+i][sy], t); return; } ... The no 2D array, actually not even a 1D array or array of pointers.
🌐
Arduino Forum
forum.arduino.cc › projects › programming
memcpy - First 2 elements in the new array are 8 and 255 [solved] - Programming - Arduino Forum
June 19, 2018 - Hello. As the title suggests, when I copy an array, the first two elements of the copy become 8 and 255. I'm using a 2D array and an Arduino Mega. Array definition - The values are just for testing purpose, generally those will be HEX values for data and address of some registers. const uint8_t E1_OTP0[3][10] = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, {20, 21, 22, 23, 24, 25,...
🌐
Stack Overflow
stackoverflow.com › questions › 51085950 › how-to-memcpy-into-a-two-dimensional-array-in-structured-text
How to memcpy into a two dimensional array in Structured Text? - Stack Overflow
int a[100][100]; int c[10][10]; int i; for(i = 0; i<10; i++) { memcpy(&a[i], &c[i], sizeof(c[0])); } How to do this in Structured Text? My analogous Approach does not work so far. (Compiler Error: to less indices for field a). VAR a: ARRAY[0..99,0..99] OF REAL; (*2D array*) c : ARRAY[0..99] OF REAL; (*1D array*) END_VAR FOR i:=0 TO 99 DO memcpy(ADR(a[i]), ADR(c[i]), SIZEOF(c[0])); END_FOR ·
Top answer
1 of 7
47

You could use memcpy.

If the multidimensional array size is given at compile time, i.e mytype myarray[1][2], then only a single memcpy call is needed

memcpy(dest, src, sizeof (mytype) * rows * columns);

If, like you indicated the array is dynamically allocated, you will need to know the size of both of the dimensions as when dynamically allocated, the memory used in the array won't be in a contiguous location, which means that memcpy will have to be used multiple times.

Given a 2d array, the method to copy it would be as follows:

char** src;
char** dest;

int length = someFunctionThatFillsTmp(src);
dest = malloc(length*sizeof(char*));

for ( int i = 0; i < length; ++i ){
    //width must be known (see below)
    dest[i] = malloc(width);

    memcpy(dest[i], src[i], width);
}

Given that from your question it looks like you are dealing with an array of strings, you could use strlen to find the length of the string (It must be null terminated).

In which case the loop would become

for ( int i = 0; i < length; ++i ){
    int width = strlen(src[i]) + 1;
    dest[i] = malloc(width);    
    memcpy(dest[i], src[i], width);
}
2 of 7
10

When you have a pointer to a pointer in C, you have to know how the data is going to be used and laid out in the memory. Now, the first point is obvious, and true for any variable in general: if you don't know how some variable is going to be used in a program, why have it? :-). The second point is more interesting.

At the most basic level, a pointer to type T points to one object of type T. For example:

int i = 42;
int *pi = &i;

Now, pi points to one int. If you wish, you can make a pointer point to the first of many such objects:

int arr[10];
int *pa = arr;
int *pb = malloc(10 * sizeof *pb);

pa now points to the first of a sequence of 10 (contiguous) int values, and assuming that malloc() succeeds, pb points to the first of another set of 10 (again, contiguous) ints.

The same applies if you have a pointer to a pointer:

int **ppa = malloc(10 * sizeof *ppa);

Assuming that malloc() succeeds, now you have ppa pointing to the first of a sequence of 10 contiguous int * values.

So, when you do:

char **tmp = malloc(sizeof(char *)*CR_MULTIBULK_SIZE);

tmp points to the first char * object in a sequence of CR_MULTIBULK_SIZE such objects. Each of the pointers above is not initialized, so tmp[0] to tmp[CR_MULTIBULK_SIZE-1] all contain garbage. One way to initialize them would be to malloc() them:

size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
    tmp[i] = malloc(...);

The ... above is the size of the ith data we want. It could be a constant, or it could be a variable, depending upon i, or the phase of the moon, or a random number, or anything else. The main point to note is that you have CR_MULTIBULK_SIZE calls to malloc() in the loop, and that while each malloc() is going to return you a contiguous block of memory, the contiguity is not guaranteed across malloc() calls. In other words, the second malloc() call is not guaranteed to return a pointer that starts right where the previous malloc()'s data ended.

To make things more concrete, let's assume CR_MULTIBULK_SIZE is 3. In pictures, your data might look like this:

     +------+                                          +---+---+
tmp: |      |--------+                          +----->| a | 0 |
     +------+        |                          |      +---+---+
                     |                          |
                     |                          |
                     |         +------+------+------+
                     +-------->|  0   |  1   |  2   |
                               +------+------+------+
                                   |      |
                                   |      |    +---+---+---+---+---+
                                   |      +--->| t | e | s | t | 0 |
                            +------+           +---+---+---+---+---+
                            |
                            |
                            |    +---+---+---+
                            +--->| h | i | 0 |
                                 +---+---+---+

tmp points to a contiguous block of 3 char * values. The first of the pointers, tmp[0], points to a contiguous block of 3 char values. Similarly, tmp[1] and tmp[2] point to 5 and 2 chars respectively. But the memory pointed to by tmp[0] to tmp[2] is not contiguous as a whole.

Since memcpy() copies contiguous memory, what you want to do can't be done by one memcpy(). Further, you need to know how each tmp[i] was allocated. So, in general, what you want to do needs a loop:

char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
/* assume malloc succeeded */
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i) {
    realDest[i] = malloc(size * sizeof *realDest[i]);
    /* again, no error checking */
    memcpy(realDest[i], tmp[i], size);
}

As above, you can call memcpy() inside the loop, so you don't need nested loop in your code. (Most likely memcpy() is implemented with a loop, so the effect is as if you had nested loops.)

Now, if you had code like:

char *s = malloc(size * CR_MULTIBULK_SIZE * sizeof *s);
size_t i;
for (i=0; i < CR_MULTIBULK_SIZE; ++i)
    tmp[i] = s + i*CR_MULTIBULK_SIZE;

I.e., you allocated contiguous space for all the pointers in one malloc() call, then you can copy all the data without a loop in your code:

size_t i;
char **realDest = malloc(CR_MULTIBULK_SIZE * sizeof *realDest);
*realDest = malloc(size * CR_MULTIBULK_SIZE * sizeof **realDest);
memcpy(*realDest, tmp[0], size*CR_MULTIBULK_SIZE);

/* Now set realDest[1]...realDest[CR_MULTIBULK_SIZE-1] to "proper" values */
for (i=1; i < CR_MULTIBULK_SIZE; ++i)
    realDest[i] = realDest[0] + i * CR_MULTIBULK_SIZE;

From the above, the simple answer is, if you had more than one malloc() to allocate memory for tmp[i], then you will need a loop to copy all the data.

Top answer
1 of 1
43

If you actually had a 2-D array, that memcpy call would work. But you don't, you have width separate discontiguous 1-D arrays, collected in an array of pointers.

It is possible to dynamically allocate a contiguous block where row and column count both vary at runtime, and preserve the two-subscript access. You'll have to change the allocation code as follows:

GridUnit** newGrid;
newGrid = new GridUnit*[width];
newGrid[0] = new GridUnit[width * height];
for (int i = 1; i < width; i++)
    newGrid[i] = newGrid[i-1] + height;

Deallocation becomes simpler:

delete[] newGrid[0];
delete[] newGrid;

There's no delete[] for newGrid[i] with i > 0 because they don't have their own blocks, they just point into the single large block. Because everything is contiguous, you can think of newGrid[0] either as a pointer to the first row (height elements), or the entire 2-D array (width * height elements).

And you can then access all the data as a single contiguous block:

memcpy(newGrid[0], oldGrid[0], height * width * sizeof newGrid[0][0]);

Of course, one shouldn't use raw pointers for memory ownership. A smart pointer will ensure the memory is properly deleted even with exceptional flow control. It would look like this:

std::unique_ptr<GridUnit[]> newData;
std::unique_ptr<GridUnit*[]> newGrid;
// before C++14 use // newData.reset(new GridUnit[width * height]);
newData = std::make_unique<GridUnit[]>(width * height);
// before C++14 use // newGrid.reset(new GridUnit*[width]);
newGrid = std::make_unique<GridUnit*[]>(width);
for (int i = 0; i < width; i++)
    newGrid[i] = &newData[i * height];