C 如何分配数组起始负索引
我正在尝试分配一个3D阵列u[-nx/2:nx/2-1][-nx/2:nx/2-1][-nx/2:nx/2-1]C 如何分配数组起始负索引,c,C,我正在尝试分配一个3D阵列u[-nx/2:nx/2-1][-nx/2:nx/2-1][-nx/2:nx/2-1] int nx = 512; double *** u = (double ***)malloc(nx * sizeof(double**)); for (int i = -nx/2; i < nx/2; i++) { u[i] = (double **)malloc(nx * sizeof(double *)); for
int nx = 512;
double *** u = (double ***)malloc(nx * sizeof(double**));
for (int i = -nx/2; i < nx/2; i++) {
u[i] = (double **)malloc(nx * sizeof(double *));
for (int j = -nx/2; j < nx/2; j++) {
u[i][j] = (double *)malloc(nx * sizeof(double));
}
}
intnx=512;
双***u=(双***)malloc(nx*sizeof(双***));
for(int i=-nx/2;i
这是正确的方法吗?如果不是,我应该如何更改它?不,这不正确。你可以通过把每个指针放在它表示的维度中间:
intnx=512;
双***u=(双***)malloc(nx*sizeof(双***))+nx/2;
for(int i=-nx/2;i
但这是不寻常的和令人困惑的,需要进行大量单独的分配,并且必须在解除分配步骤中撤消
考虑一个具有访问器的块:
#定义NX 512
/*如果nx是动态的,则只需加倍*即可,并手动计算索引*/
双[NX][NX][NX]*u=malloc(sizeof(*u));
双数组(双[NX][NX][NX]const*u,int i,int j,int k){
返回u[i+NX/2][j+NX/2][k+NX/2];
}
无效数组_集(双[NX][NX][NX]*u,int i,int j,int k,双值){
u[i+NX/2][j+NX/2][k+NX/2]=值;
}
不,那不正确。你可以通过把每个指针放在它表示的维度中间:
intnx=512;
双***u=(双***)malloc(nx*sizeof(双***))+nx/2;
for(int i=-nx/2;i
但这是不寻常的和令人困惑的,需要进行大量单独的分配,并且必须在解除分配步骤中撤消
考虑一个具有访问器的块:
#定义NX 512
/*如果nx是动态的,则只需加倍*即可,并手动计算索引*/
双[NX][NX][NX]*u=malloc(sizeof(*u));
双数组(双[NX][NX][NX]const*u,int i,int j,int k){
返回u[i+NX/2][j+NX/2][k+NX/2];
}
无效数组_集(双[NX][NX][NX]*u,int i,int j,int k,双值){
u[i+NX/2][j+NX/2][k+NX/2]=值;
}
首先,所有C数组的索引值范围为
0
到元素计数-1
。总是
当您使用malloc时,我假定nx
的值仅在运行时定义。这排除了静态数组大小,因此排除了使用cutearr[x][y][z]
语法,如中所示:
#define NX 512
double arr[NX][NX][NX];
void foo(void)
{
...
arr[z1][y1][x1] += 2 * arr[z2][y2][x2];
...
}
这反过来意味着,要使3D阵列的功能具有nx
不同的三维值,您需要分配一个大小为nx\u cubed=nx*nx*nx
的线性存储区域。要正确计算该值nx_cubed
,需要检查整数溢出
此外,还需要将有符号的int
坐标值正确转换为基于0的索引范围中使用的无符号size\t
值
if (nx < 0) {
fprintf(stderr, "negative value of nx\n");
exit(EXIT_FAILURE);
}
const size_t unx = nx;
const size_t nx_cubed = unx * unx * unx;
/* TODO: Complete check for overflows */
if (nx_cubed < unx) {
fprintf(stderr, "nx_cubed overflow\n");
exit(EXIT_FAILURE);
}
现在的问题是从x
、y
和z
值计算数组索引,每个值的范围从-nx/2
到nx/2-1
。我建议编写一个函数,将该范围映射到0
到nx-1
范围,然后根据三个基于0的值计算适当的线性指数。同样,应执行适当的整数溢出检查
size_t array3index(const size_t nx, const int x, const int y, const int z) {
const size_t half_nx = nx/2;
/* zero based 3D coordinates,
* this probably triggers some signedness warnings */
const size_t x0 = half_nx + x;
const size_t y0 = half_nx + y;
const size_t z0 = half_nx + z;
if ((x0 >= nx) || (y0 >= nx) || (z0 >= nx)) {
fprintf(stderr, "Signed coordinate(s) out of range: (%d, %d, %d)\n",
x, y, z);
exit(EXIT_FAILURE);
}
const size_t idx = nx * (nx * z0 + y0) + x0;
/* Assuming that we have already checked that nx*nx*nx does not
* overflow, and given that we have checked for x0, y0, z0 to be
* in the range of 0 to (nx-1), the idx calculation should not
* have overflown here. */
return idx;
}
然后您可以访问3D阵列,如
const i1 = array3index(nx, x1, y1, z1);
const i2 = array3index(nx, x2, y2, z2);
buf[i1] += 2*buf[i2];
考虑到
array3index
中需要的计算量,我将检查直接在0
到nx-1
域中进行数组迭代是否更有意义,如果您在计算中实际需要范围值,则仅将其转换为-nx/2
到nx/2-1
范围值。首先,所有C数组的索引值范围为0
到元素计数-1
。总是
当您使用malloc时,我假定nx
的值仅在运行时定义。这排除了静态数组大小,因此排除了使用cutearr[x][y][z]
语法,如中所示:
#define NX 512
double arr[NX][NX][NX];
void foo(void)
{
...
arr[z1][y1][x1] += 2 * arr[z2][y2][x2];
...
}
这反过来意味着,要使3D阵列的功能具有nx
不同的三维值,您需要分配一个大小为nx\u cubed=nx*nx*nx
的线性存储区域。要正确计算该值nx_cubed
,需要检查整数溢出
此外,还需要将有符号的int
坐标值正确转换为基于0的索引范围中使用的无符号size\t
值
if (nx < 0) {
fprintf(stderr, "negative value of nx\n");
exit(EXIT_FAILURE);
}
const size_t unx = nx;
const size_t nx_cubed = unx * unx * unx;
/* TODO: Complete check for overflows */
if (nx_cubed < unx) {
fprintf(stderr, "nx_cubed overflow\n");
exit(EXIT_FAILURE);
}
现在的问题是从x
、y
和z
值计算数组索引,每个值的范围从-nx/2
到nx/2-1
。我建议编写一个函数,将该范围映射到0
到nx-1
范围,然后根据三个基于0的值计算适当的线性指数。同样,应执行适当的整数溢出检查
size_t array3index(const size_t nx, const int x, const int y, const int z) {
const size_t half_nx = nx/2;
/* zero based 3D coordinates,
* this probably triggers some signedness warnings */
const size_t x0 = half_nx + x;
const size_t y0 = half_nx + y;
const size_t z0 = half_nx + z;
if ((x0 >= nx) || (y0 >= nx) || (z0 >= nx)) {
fprintf(stderr, "Signed coordinate(s) out of range: (%d, %d, %d)\n",
x, y, z);
exit(EXIT_FAILURE);
}
const size_t idx = nx * (nx * z0 + y0) + x0;
/* Assuming that we have already checked that nx*nx*nx does not
* overflow, and given that we have checked for x0, y0, z0 to be
* in the range of 0 to (nx-1), the idx calculation should not
* have overflown here. */
return idx;
}
然后您可以访问3D阵列,如
const i1 = array3index(nx, x1, y1, z1);
const i2 = array3index(nx, x2, y2, z2);
buf[i1] += 2*buf[i2];
考虑到array3index
中需要的计算量,我将检查直接在0
到nx-1
域中进行数组迭代是否更有意义,如果您在计算中实际需要范围值,则仅将其转换为-nx/2
到nx/2-1
范围值。否。
C中的数组实际上只是普通/平面内存块,它总是基于0,并且总是在