1

我有一个固定宽度的坐标系

#define gridSize 101
int _map[gridSize][gridSize];

由于我获得了某些 xy 坐标的值,范围从 -50 到 50,因此我想调用我的地图,例如map[0][0]作为指向的坐标原点_map[51][51]。换句话说,如果我从我的源获得 xy 的值并想将其添加到我的地图中,我想调用

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

最后一行代码是错误的。我该怎么做?

4

3 回答 3

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大数。

于 2012-06-15T09:54:01.603 回答
1

是的你可以!

我不认为你可以用数组来做到这一点,但你可以用指向数组元素的指针来做到这一点。

但是,除非我有很好的理由,否则我不会这样做。负可索引指针不会是阅读您的代码的人所期望的,因此很容易意外误用。为清楚起见,使用基于函数的解决方案可能会更好 - 除非它需要非常快。

有了这个,让我们开始吧!

从您的尝试来看,您似乎对数组和指针感到困惑。请记住,它们不是一回事

现在,C 不会阻止您使用负索引,这在您使用指针时是有意义的。所以,你可以这样做:

 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]。这实际上与普通的二维数组没有什么不同,但在调试时需要注意这一点。

于 2012-06-15T13:30:10.477 回答
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;
}
于 2012-06-15T10:51:35.437 回答