简体   繁体   English

复制多维数组(指针)

[英]copying multidimensional array (pointers)

I have two structs pointers to pointers 我有两个指向结构的指针

typedef struct Square {
...
...
}Square;

Square **s1; //Representing 2D array of say, 100*100
Square **s2; //Representing 2D array of say, 200*200

Both are allocated on the heap using malloc() . 两者都使用malloc()在堆上分配。 I have s1 initialized with certain values and s2 initialized completely with the default values. 我已将s1初始化为某些值,并将s2完全初始化为默认值。 Basically I need to resize s1 to the size of s2 while maintaining its ( s1 ) values, and the 'added' values would be just as they were in s2 - the default value. 基本上,我需要将s1的大小调整为s2的大小,同时保持其( s1 )值,并且“添加”的值将与它们在s2的值相同-默认值。

I wrote this question memcpy() from smaller array to larger one but apparently I'm confusing between arrays and pointers/ 我写了这个问题memcpy()从较小的数组到较大的数组,但是显然我在数组和指针之间感到困惑/

My question is, how to implement this resizing of s1 to the size of s2 . 我的问题是,如何将s1的大小调整为s2的大小。 I don't have to keep the original pointer. 我不必保留原始指针。 I can copy s1 to s2 and return s2 if that's a better way I hope I explained what I'm after properly. 我可以将s1复制到s2并返回s2 ,这是一个更好的方法,希望我能正确解释一下。 Thanks! 谢谢!

Two dimensional arrays are laid out in memory sequentially: row1 row2 row3 etc. 二维数组按顺序排列在内存中:row1 row2 row3等。

memcpy does a linear copy from one memory location to another. memcpy从一个内存位置到另一个内存位置进行线性复制。

So to achieve what you need: 因此,要实现您所需要的:

a) Create a new array a)创建一个新数组

Square **s3 = malloc(sizeof(s2));

b) Copy s2 into it b)将s2复制到其中

c) Copy stuff from s1, row by row into new c)从s1逐行复制内容到新内容

for(r = 0; r < NROWS_S1; r++)
    memcpy(s3[r], s1[r], sizeof(Square) * NCOLS_S1);

http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html http://www.fredosaurus.com/notes-cpp/arrayptr/23two-dim-array-memory-layout.html

You can try something like this: 您可以尝试如下操作:

typedef struct {
    //
} Square;

Square** s1; // 100x100, needs to resize and be like s2.
Square** s2; // 200x200

void resize_s1()
{
    // resize the outer array
    s1 = realloc(s1, sizeof(Square*)*200);
    memset(s1 + 100, 0, 100*sizeof(Square*)); // we initialize the newly allocated pointers to NULL

    for(int i = 0; i < 200; ++i)
    {
        // resize the inner array. Since we initialized the last
        // 100 pointers to null, realloc will just behave like
        // malloc for them.
        s1[i] = realloc(s1[i], 200*sizeof(Square));

        // ... and copy the new values in! You can omit this step,
        // but anything outside of the original bounds of s1 will
        // be uninitialized. All your pointers will be valid though.
        if(i >= 100)
            memcpy(s1[i] + 100, s2[i] + 100, 100*sizeof(Square));
    }
}

As a word of warning - I'm playing very fast and loose with realloc here. 值得一提的是-我在这里玩得非常快,并且在进行realloc操作。 Read its man page for more details, but if you ever hit low memory conditions, bad things can happen. 阅读其手册页以获取更多详细信息,但是如果遇到内存不足的情况,可能会发生不良情况。

You've allocated your 2-D matrix on the heap, and you're using a Square** to access it. 您已经在堆上分配了二维矩阵,并且正在使用Square**进行访问。 This means that you've: (1) allocated the space for each element in one or more calls to malloc , and (2) allocated the space for all of the row pointers in a call to malloc . 这意味着您已经:(1)在对malloc一个或多个调用中为每个元素分配了空间,并且(2)在对malloc的调用中为所有行指针分配了空间。 How to proceed depends quite a lot of how you've allocated the array. 如何进行取决于您如何分配数组。

Below, I use assert to stress that each malloc/realloc can return NULL (indicating that it could not complete the request). 在下面,我使用assert来强调每个malloc / realloc都可以返回NULL(指示它无法完成请求)。 You'll probably want to handle these cases properly. 您可能需要适当处理这些情况。

Option 1: You allocated each row separately 选项1:您分别分配了每一行

You allocated the s1 matrix like this: 您分配了s1矩阵,如下所示:

Square** s1 = malloc(M1*sizeof(s1[0]));
for (size_t i=0; i < M1; i++)
  s1[i] = malloc(N1*sizeof(s1[i][0]));

In this case, you have to handle each row separately: 在这种情况下,您必须分别处理每一行:

/* M1 and N1 set to size of s1 (M1 x N1) */
/* M2 and N2 set to size of s2 (M2 x N2) */

/* First, reallocate the pointers to each row */
Square** tmpRows = realloc(s1, M2*sizeof(*tmpRows));
assert( (tmpRows != NULL) && "Out of memory reallocating rows" );

s1 = tmpRows;

/* Now, reallocate each row */
for (size_t i=0; i < M1; i++) {
  Square* tmpVals = realloc(s1[i], N2*sizeof(tmpVals[0]));
  assert( (tmpVals != NULL) && "Out of memory reallocating row" );

  /* copy elements of s2 into new column */
  memcpy(tmpVals+N1, s2[i]+N1, (N2-N1)*sizeof(s1[i][0]));
  s1[i] = tmpVals;
}

/* Now, allocate each new row of s1 and copy the additional rows of s2 into s1 */
for (size_t i=M1; i < M2; i++) {
  s1[i] = malloc( N2 * sizeof(s1[i][0]) );
  assert( (s1[i] != NULL) && "Out of memory allocating new row" );
  memcpy(s1[i], s2[i], N2*sizeof(s1[i][0]));
}

Option 2: You allocated each all of the rows at once 选项2:您一次分配了所有行

In this case, you allocated all of the rows in one big chunk, and then assigned pointers to the beginning of each row. 在这种情况下,您将所有行分配为一个大块,然后将指针分配给每一行的开头。 Like this: 像这样:

Square** s1 = malloc(M1*sizeof(s1[0]));
s1[0] = malloc( M1*N1*sizeof(s1[0][0]) );
for(size_t i=1; i < M1; i++) 
  s1[i] = s1[i-1] + N1;

To resize the array (and initialize its new elements with those of s2), you should do the following: 要调整数组的大小(并使用s2的元素初始化其新元素),应执行以下操作:

/* M1 and N1 set to size of s1 (M1 x N1) */
/* M2 and N2 set to size of s2 (M2 x N2) */

/* Make a new copy of the elements of s1.  Linear layout of a 200x200 
 * matrix will be different than the linear layout of a 100x100 matrix.
 * Making a new copy makes it easier to initialize its values.
 */
Square* new_mat = malloc( M2*N2*sizeof(new_mat[0]) );
assert( (new_mat != NULL) && "Out of memory allocating new matrix" );

/* Initialize with values of s2.  Assumption: s2 is also allocated
 * as a contiguous array...
 */
memcpy(new_mat, s2[0], M2*N2*sizeof(s2[0][0]));

/* Now, reallocate the rows */
Square** tmpRows = realloc(s1, M2*sizeof(s1[0]));
assert( (tmpRows != NULL) && "Out of memory reallocating rows" );

s1 = tmpRows;
/* Copy data from old rows into new rows... */
for (size_t i=0; i < M1; i++) {
  /* rows of s1 still point to old_mat data, copy it into new_mat.
   * Each row in new_mat starts at (new_mat + N2*i)
   */
  memcpy( new_mat + N2*i, s1[i], N1*sizeof(s1[i][0]) );
}

/* Free old memory and assign new row pointers... */
free(s1[0]);
s1[0] = new_mat;
for (size_t i=1; i < M2; i++)
  s1[i] = s1[i-1] + N2;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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