使用 memmove 将元素移动一个索引
Shift elements by one index with memmove
我正在尝试将动态创建的 3d 数组中的元素移动一个索引,以便每个元素 [i][j][k]
应该在 [i+1][j][k]
.
上
这就是我创建数组的样子
typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;
void createMatrix(matrix *vector){
vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
for (int j = 0; j < vector->m+2; ++j) {
vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
}
}
}
这基本上就是我想用 memmove 实现的目标
for(int i = vector->l-1; i >= 0; --i){
for(int j = vector->m; j >= 0; --j){
for(int k = vector->n; k >= 0; --k){
vector->arr[i+1][j][k] = vector->arr[i][j][k];
}
}
}
出于某种原因,memmove 移动了 2 个索引。
memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));
有人可以给我提示吗?
简单地这样做就可以了(在 3d 数组中说明)
memmove(arr[1], arr[0], Y*Z*sizeof(int));
其中 Y
和 Z
表示二维数组的其他两个维度。
此处 arr[X][Y][Z]
是 int
数组,其中 X>=2
.
在动态分配内存的情况下,您需要一个接一个地处理每个连续的块。然后它会起作用。
使用更高的优化级别编译 (-O3
)。在 vector->arr
上获取直接引用,而不是在每次访问数组时都强制取消引用。
在您将 arr
分配为连续内存的假设下,您对 memmove
的调用看起来只对了一半。但是,既然你说"dynamic",我很怀疑。再加上大小计算出现了很大的错误,sizeof(int*)
.
我想arr
不是int arr[constexpr][constexpr][constexpr]
(单次连续分配),而是int ***arr
.
在这种情况下,memmove
就大错特错了。在将 arr
字段的 int**
内容移动一个(实际上已经进行了移动)之后,它导致了堆上的严重溢出,很可能偶然也击中了 [=21] 的大部分=] 分配如下。
看起来像双步移动,留下完全毁坏的堆。
当您像这样创建一个动态多维数组时,数组内容不是连续的——每一行都是一个单独的分配。所以你不能用一个 memmov()
.
移动它
但不需要复制所有数据,只需将顶层数组中的指针移位即可。
int **temp = arr[l-1]; // save last pointer, which will be overwritten
memmov(&arr[1], &arr[0], sizeof(*arr[1]));
arr[0] = temp;
我已将最后一个元素移到第一个,以避免两个元素指向相同的数据。您还可以释放旧的最后一个元素(包括释放它指向的数组)并创建一个新的第一个元素,但这更简单。
我正在尝试将动态创建的 3d 数组中的元素移动一个索引,以便每个元素 [i][j][k]
应该在 [i+1][j][k]
.
这就是我创建数组的样子
typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;
void createMatrix(matrix *vector){
vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
for (int j = 0; j < vector->m+2; ++j) {
vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
}
}
}
这基本上就是我想用 memmove 实现的目标
for(int i = vector->l-1; i >= 0; --i){
for(int j = vector->m; j >= 0; --j){
for(int k = vector->n; k >= 0; --k){
vector->arr[i+1][j][k] = vector->arr[i][j][k];
}
}
}
出于某种原因,memmove 移动了 2 个索引。
memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));
有人可以给我提示吗?
简单地这样做就可以了(在 3d 数组中说明)
memmove(arr[1], arr[0], Y*Z*sizeof(int));
其中 Y
和 Z
表示二维数组的其他两个维度。
此处 arr[X][Y][Z]
是 int
数组,其中 X>=2
.
在动态分配内存的情况下,您需要一个接一个地处理每个连续的块。然后它会起作用。
使用更高的优化级别编译 (-O3
)。在 vector->arr
上获取直接引用,而不是在每次访问数组时都强制取消引用。
在您将 arr
分配为连续内存的假设下,您对 memmove
的调用看起来只对了一半。但是,既然你说"dynamic",我很怀疑。再加上大小计算出现了很大的错误,sizeof(int*)
.
我想arr
不是int arr[constexpr][constexpr][constexpr]
(单次连续分配),而是int ***arr
.
在这种情况下,memmove
就大错特错了。在将 arr
字段的 int**
内容移动一个(实际上已经进行了移动)之后,它导致了堆上的严重溢出,很可能偶然也击中了 [=21] 的大部分=] 分配如下。
看起来像双步移动,留下完全毁坏的堆。
当您像这样创建一个动态多维数组时,数组内容不是连续的——每一行都是一个单独的分配。所以你不能用一个 memmov()
.
但不需要复制所有数据,只需将顶层数组中的指针移位即可。
int **temp = arr[l-1]; // save last pointer, which will be overwritten
memmov(&arr[1], &arr[0], sizeof(*arr[1]));
arr[0] = temp;
我已将最后一个元素移到第一个,以避免两个元素指向相同的数据。您还可以释放旧的最后一个元素(包括释放它指向的数组)并创建一个新的第一个元素,但这更简单。