我有一个固定宽度的坐标系
#define gridSize 101
int _map[gridSize][gridSize];
由于我得到的某些x y坐标值介于-50到50之间,因此我希望将我的地图称为map[0][0]
,作为指向_map[51][51]
的纵坐标的原点。
换句话说,如果我从我的源码获取x y的值并想将其添加到我的地图中,我想调用
map[x][y] = value
实际得到的是
_map[51+x][51+y] = value
所以我必须创建一个指针,但我不知道如何在多维数组中这样做。
#define gridSize 101 // must be an odd number for origin of ordinates in center
#define gridSizeCenter = (int)(gridSize/2)+1;
int _map[gridSize][gridSize];
int map[gridSize][gridSize];
map = &_map[gridSizeCenter][gridSizeCenter]; // wont work
最后一行代码是错误的。我该怎么做?
答案 0 :(得分:1)
你不能这样做。最好的解决方案可能是拥有一组访问_map
变量的函数。类似的东西:
void set_map_value(int map[][gridSize], const int value, const int x, const int y)
{
map[x + 51][y + 51] = value;
}
int get_map_value(int map[][gridSize], const int x, const int y)
{
return map[x + 51][y + 51];
}
使用函数可以进行类型检查,还可以对坐标进行范围检查。
您不能按照自己的意愿去做的一个原因,以及编译错误的原因是类型不兼容。
另一个原因是你真的不能在数组中有负索引。请记住,整数 -1
与0xffffffff
相同,即4294967295
,它是数组范围内的大数方式。
答案 1 :(得分:1)
我不认为你可以用数组做这个,但你可以用指向数组元素的指针来做。
然而,我不会这样做,除非我有一个非常好的理由。负索引指针不会是读取代码的人所期望的,因此很容易被误导。为清楚起见,使用基于功能的解决方案可能会更好 - 除非它需要非常快。
有了这个,让我们做吧!
从您的尝试来看,您可能会对数组和指针感到困惑。请记住,他们are not the same thing。
现在,C不会阻止您使用负面索引which can make sense when you're using a pointer。所以,你可以这样做:
int a[5];
int *b = a + 2; // or &a[2]
b[-2] // is a[0]
b[-1] // is a[1]
b[0] // ia a[2], etc
因此,我认为以下代码适合您。
#define GRIDSIZE 101
.....
int map_memory[GRIDSIZE][GRIDSIZE];
int *map_rows[GRIDSIZE];
int **map;
int i;
int gridMidPoint = GRIDSIZE / 2;
for(i = 0; i < GRIDSIZE; i++) {
map_rows[i] = &(map_memory[i][0]) + gridMidPoint;
}
map = map_rows + gridMidPoint;
然后您可以完全按照您的预期使用它 - 网格大小为101:
for(i = -50; i <= 50; i++) {
for(j = -50; j <= 50; j++) {
map[i][j] = i+j;
}
}
或者,更一般地说:
for(i = -1 * gridMidPoint; i <= gridMidPoint; i++) {
for(j = -1 * gridMidPoint; j <= gridMidPoint; j++) {
map[i][j] = i+j;
}
}
由于两个数组都是在堆栈上创建的,因此不需要释放任何数据。
这里发生了什么?让我分解一下。首先,我们创建支持数组:
int map_memory[GRIDSIZE][GRIDSIZE];
接下来,我们想要一个我们将用作行的指针数组:
int *map_rows[GRIDSIZE];
我们需要将它们作为指针,因为它们将指向我们刚刚制作的二维数组中的数组中间。
int gridMidPoint = GRIDSIZE / 2;
这里我们计算中点。我假设你想在零的每一边都有相同数量的数组元素 - 所以你不需要你的例子中的+1。
for(i = 0; i < GRIDSIZE; i++) {
map_rows[i] = &(map_memory[i][0]) + gridMidPoint;
}
此代码遍历rows数组中的每个元素,并将该行设置为指向二维数组中相关行的中间。你也可以写:
map_rows[i] = &map_memory[i][gridMidPoint];
但我个人认为带有超级括号和添加的版本更清晰易读。我想如果你用指针做一些不寻常的事情,你应该清楚地说出下一个读你代码的人正在发生什么。
最后,我们需要我们的map
指针指向行的中间:
map = map_rows + gridMidPoint;
我们已经完成了!
请记住,二维数组实际上是一块连续的内存。这意味着map[0][gridMidPoint+1]
与map[1][-1*gridMidPoint]
的位置相同。这实际上与普通的二维数组没有什么不同,但是在调试时需要注意这一点。
答案 2 :(得分:0)
您可以使用此解决方案
#define gridSize 101 // must be an odd number for origin of ordinates in center
#define gridSizeCenter gridSize/2 +1
int main (int argc, char *argv[]) {
int _map[gridSize][gridSize];
#define MAP(A,B) _map[A+gridSizeCenter][B+gridSizeCenter]
MAP(-1,-1) = 5;
MAP(0,0) = 6;
printf ("MAP(0,0) = %d\r\nMAP(-1,-1) = %d\r\n",MAP(0,0),MAP(-1,-1));
return 0;
}