是的,你可以!
我不认为你可以用数组做到这一点,但你可以与指针数组元素做。
然而,我不会这样做,除非我有一个非常好的理由。否定索引的指针不会成为阅读你的代码的人会期望的东西,所以它会很容易被误操作。为了清楚起见,使用基于功能的解决方案可能会更好 - 除非它需要非常快。
就这样,让我们来做吧!
从您的尝试中,您可能会对数组和指针感到困惑。请记住,他们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]
与位置相同。这实际上与普通的二维数组没有什么不同,但是它在调试时需要注意。
通常的做法是使#define大写,例如#define GRIZIZE。否则,他们看起来像变量。 – 2012-06-15 09:59:08