2012-06-15 56 views
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 

最后一行代码错误。我该如何做对?

+3

通常的做法是使#define大写,例如#define GRIZIZE。否则,他们看起来像变量。 – 2012-06-15 09:59:08

回答

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]; 
} 

使用函数为您提供类型检查,并且还允许您范围检查坐标。


一个原因就像你想你不能做到这一点,你的编译错误的原因,是该类型不兼容。

另一个原因是你真的不能在数组中有负指数。请记住,整数 -10xffffffff相同,即 4294967295这是一个大数字 的方式超出了数组范围。

+2

我不相信C标准要求数组/指针下标中的无符号整数,所以我认为您对有符号值的无符号表示的评论是有误导性的。 –

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; 
} 
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; 
} 

该代码遍历我们行数组中的每个元素,并将该行设置为指向二维数组中的相关行的中间。你也可以写:

map_rows[i] = &map_memory[i][gridMidPoint]; 

但是我个人认为,随着superflous支架和另外的版本更加清晰易读。我认为如果你用指针做了不寻常的事情,你应该明确地说明下一个阅读代码的人会发生什么。

最后,我们需要我们的map指针指向行的中间:

map = map_rows + gridMidPoint; 

,我们就大功告成了!


记住二维阵列实际上是连续的存储器的一个块。这意味着map[0][gridMidPoint+1]与​​位置相同。这实际上与普通的二维数组没有什么不同,但是它在调试时需要注意。