如何定义一个动态的数组?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何定义一个动态的数组?相关的知识,希望对你有一定的参考价值。
参考技术A利用这一特性定义一个指针数组。
int **p= new int*[size];//定义指针数组
int *p[5];// 假若知道二维数组的行数为5
然后对指针数组中的每一个指针分配一个一维数组空间,这样便动态定义了二维数组
事实上,我认为指针数组的主要用途,就在于动态定义多维数组
for(int i=0;i<size;i++)
p[i]=new int[Column];
运行完毕后,一个二维数组便被动态的成功建立。
动态数组,是相对于静态数组而言。静态数组的长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。而动态数组则不然,它可以随程序需要而重新指定大小。动态数组的内存空间是从堆(heap)上分配(即动态分配)的。是通过执行代码而为其分配存储空间。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。
为什么要使用动态数组?
在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。对于这种问题,用静态数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数结合指针可以按需要动态地分配内存空间,来构建动态数组,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
动态数组与静态数组的对比
对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!
对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则严重会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。
如何使用 MPI 传输带有动态数组的自定义结构?
【中文标题】如何使用 MPI 传输带有动态数组的自定义结构?【英文标题】:How to use MPI to transfer a custom struct with a dynamic array? 【发布时间】:2020-05-13 18:50:42 【问题描述】:有一个简单的例子来描述我的问题。 我有一个包含动态数组的自定义结构
struct my_data_type
int c;
int d[];
;
根进程(进程0)有一个这样的结构数组nums[4]
。
我想通过MPI_Scatter
将数组的块发送到不同的进程(例如,2 个进程)。这里的主要问题是我希望这个数组d[]
是动态的。
主要代码如下:
int main(int argc, char* argv[])
MPI_Init(NULL, NULL);
int my_size; MPI_Comm_size(MPI_COMM_WORLD, &my_size);
int my_rank; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int len = 2; //example: the dynamic array d contains len=2 elements
my_data_type *nums //nums[4]
= (my_data_type*)malloc((sizeof(my_data_type) + sizeof(int) * len) * 4);
my_data_type *sub_nums //sub_nums[2]
= (my_data_type*)malloc((sizeof(my_data_type) + sizeof(int) * len) * 2);
if (my_rank == 0) //just some examples
nums[0].c = 0; nums[1].c = 1; nums[2].c = 2; nums[3].c = 3;
nums[0].d[0] = 10; nums[1].d[0] = 11; nums[2].d[0] = 12; nums[3].d[0] = 13;
nums[0].d[1] = 14; nums[1].d[1] = 15; nums[2].d[1] = 16; nums[3].d[1] = 17;
MPI_Datatype mpi_data_type; //new datatype
int blocklens[2];
MPI_Datatype old_types[2];
MPI_Aint indices[2];
blocklens[0] = 1; blocklens[1] = len;
old_types[0] = MPI_INT; old_types[1] = MPI_INT;
MPI_Address(&nums[0].c, &indices[0]);
MPI_Address(&nums[0].d[0], &indices[1]);
indices[1] = indices[1] - indices[0];
indices[0] = 0;
MPI_Type_create_struct(2, blocklens, indices, old_types, &mpi_data_type);
MPI_Type_commit(&mpi_data_type);
MPI_Scatter(nums, 2, mpi_data_type,
sub_nums, 2, mpi_data_type,
0, MPI_COMM_WORLD);
cout << "rank " << my_rank << ": " << endl;
cout << "c: " << sub_nums[0].c << ", " << sub_nums[1].c << endl;
cout << "d: " << sub_nums[0].d[0] << ", " << sub_nums[0].d[1] << ", ";
cout << sub_nums[1].d[0] << ", " << sub_nums[1].d[1] << endl;
MPI_Finalize();
return 0;
如果我在struct my_data_type
的定义中将int d[];
改成int d[2];
,我肯定会得到像这样的预期结果
rank 0:
c: 0, 1
d: 10, 14, 11, 15
rank 1:
c: 2, 3
d: 12, 16, 13, 17
但如果不是,结果如下:
rank 0:
c: 0, 10
d: 10, 14, 14, 15
rank 1:
c: 33, 0
d: 0, 0, 0, 1
如您所见,我知道问题出在动态数组上,但我不能在我的项目中使用静态数组。那么如何更改上面的代码以获得预期的结果呢?
【问题讨论】:
如果您使用d[]
,那么 sizeof(...)
不是您所期望的,因此会出现短暂的 malloc 和数据损坏。
亲爱的朋友,感谢您的cmets。我发现了一个错误并更新了它(结构数组nums[4]
和sub_nums[4]
的malloc)。但这仍然是错误的。而且我不能 malloc 动态数组 d[]
因为数组类型 'int []' 不可分配。
我认为你不能以理智的方式使用灵活的数组成员来制作结构数组。
我同意你的看法。所以实际上我想知道如何以另一种方式处理具有灵活数组成员的结构数组。
我用如何使用 FAM 处理结构数组更新了我的答案。
【参考方案1】:
您的根本问题不是 mpi,而是使用具有灵活数组成员的 struct 数组。这是一个示例程序来说明问题
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct s s;
struct s
int c;
int d[];
;
int main(int argc, char* argv[])
assert(sizeof(s) == sizeof(int));
int len = 4;
s* okay = malloc(sizeof(*okay) + sizeof(int)*len);
intptr_t true_size = (intptr_t)&okay->d[len] -(intptr_t)(okay);
assert(true_size == ((len+1)*sizeof(int)));
int nbad = 6;
s* bad = malloc((sizeof(*bad) + sizeof(int)*len)*nbad);
intptr_t bad_size = (intptr_t)&bad[1] -(intptr_t)&bad[0];
/* this size mismatch means arrays of `s` do not do what you think they do */
assert(bad_size != true_size);
assert(bad_size == sizeof(int));
assert((char*)&bad[1] == (char*)&bad[0].d[0]);
assert((char*)&bad[2] == (char*)&bad[0].d[1]);
assert((char*)&bad[3] == (char*)&bad[0].d[2]);
assert((char*)&bad[1].d[0] == (char*)&bad[0].d[1]);
assert((char*)&bad[2].d[0] == (char*)&bad[0].d[2]);
assert((char*)&bad[3].d[0] == (char*)&bad[0].d[3]);
要处理具有灵活数组成员的结构数组,您需要手动计算用于索引的内存偏移量,而不是依赖编译器。所以你可以像这样定义一个辅助函数:
s* s_index(const s* a, int len, int index)
uintptr_t true_size = sizeof(*a) + len*sizeof(int);
return (s*)((char*)a + index * true_size);
然后使用s_index
来访问所需的数组成员,而不是bad[0]
、bad[1]
构造:
s* first = s_index(bad, len, 0);
s* second = s_index(bad, len, 1);
assert((char*)&first->d[len] == (char *)second);
【讨论】:
感谢您的帮助!!你是对的,我可以根据自己的问题进行调整。【参考方案2】:我可能错了,但我认为你想要的是保存一个指向数组的指针(即int** myArrPointer
),因为我认为你需要做的是,因为我认为你不能在 C 中分配一个数组(即myArr = myOtherArr
),是为了:
-
计算新数组的大小
为该新数组分配内存
将指向该新数组的指针存储在您的结构中
您的结构最终可能需要看起来像这样:
struct my_data_type
int ArrSize;
int** PointerToAnArray;
;
void SomeFunForSwappingArrays(my_data_type* instance, int newArrSize)
int* newArr = (int*)malloc(newArrSize*sizeof(int));
//free the memory of the old array. if you don't need the data anymore, i would
//consider doing this.
free(*(instance->PointerToAnArray));
//save the memory address of the new array
instance->PointerToAnArray = &newArr;
instance->ArrSize = newArrSize;
希望对你有帮助。
【讨论】:
感谢您的建议。但问题是向其他 MPI 节点发送指针而不是数组似乎没有意义。 检查此问题以通过 MPI 通过指针发送数据。看起来你真的可以。直到现在我还没有听说过 MPI,所以我很好奇这是否可能。 ***.com/questions/32217553/… 另外,数组在用作函数输入时无论如何都会衰减为 C 中的指针,所以对我来说,将数组放入函数中是没有意义的,而将指针放入函数中会不是。我认为由于衰减,该函数将使用指针。 我发现指针确实有效,但是当我在自定义结构中使用指针时出现问题。事实上,我的观点就像 Jeff 的评论所说:“你不能发送一个指针,因为它在分配它的进程之外是没有意义的。”一个进程的内存地址对其他进程(在其他计算机中)没有用处。 无论如何,我会尝试单独使用指针,而不是在结构中。这可能会奏效。以上是关于如何定义一个动态的数组?的主要内容,如果未能解决你的问题,请参考以下文章