How to use (2d) arrays with negative index?
In 1D you can simulate x-coordinate in such a开发者_Go百科 way:
int temp[1000];
int *x = a+500;
How can we have a grid now? (Something like a[10][-13]
.)
You can easily convert -ve and +ve integers into just +ve integers as an index into an array as you are unable to use -ve indexes.
Here is how
if (index < 0)
then index = -index * 2 - 1
else index = index * 2
i.e. -ve indexes use the odd numbers, +ve use the even numbers. 0 stays at 0.
Don't confuse mathematics with array dimensions in C/C++, those are different things. If you have a mathematical matrix with indices -500 to 500, you use a C array with indices 0 to 1000 to store it in.
However you can access an array by using a negative index, as long as you make sure you aren't accessing the array out of bounds. For example:
int arr[1000];
int* ptr = &arr[499];
printf("%d", ptr[-100]);
2D arrays work in the very same way, although strictly speaking you can still not access a sub array out of bounds and expect to end up in an adjacent array, this is undefined behavior in C/C++. But in real world implementations static 2D arrays are always allocated using adjacent memory cells, so one can often safely assume they are, no matter what the C standard says.
You just have to calculate the offsets yourself, for instance
int grid[400]; // twenty by twenty grid, origin at (10, 10)
int get_grid_value(int x, int y)
{
return grid[20*(x + 10) + (y + 10)];
}
Of course in real code you shouldn't use so many magic numbers.
First of all, this only works if the memory allocated for the array is contiguous. Then you can find out the "middle point" of the array by
int temp[5][5];
int *a = temp[2] + 2;
Or, in more general terms
int len
int *temp = malloc(len * len * sizeof(int));
int *a = temp + (len/2)*len + len/2;
If you want to simulate geometry using arrays ... you could do something like
have a variable with maximum number of points and assign a pointer to the middle value. So with that pointer you could have negative indeces.
A sample program.
int main() {
int c[10000];
int *a = &c[5000];
for(int i=-5000;i<5000;i++)
a[i] = i;
for(int i=-5000;i<5000;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
Hope this was helpful .. To use it in a more proper way, you could have a class which internally manages this. Or you could have your template.
I'm not sure you can do that with a simple 2-D array without invoking the gremlins of undefined behavior, but you could set it up as an array of pointers. Create an array of pointers to int, then set a pointer to point into the middle of the array; that gives you signed indices for the first dimension. Then set each element of the pointer array to point to an array of int, and advance each to point to the middle of that array; that gives you signed indices for the second dimension. You can use the same arr[x][y]
syntax you'd use for an actual 2-D array, but the second []
applies to an actual pointer, not an array that decayed to a pointer.
If any of these arrays are allocated with malloc()
, you must pass the original pointer to free()
.
If there's sufficient interest, I'll try to post some code later.
BTW, I'm not at all convinced this would be worth the effort. You could easily fake all this with ordinary 0-based arrays, at the cost of a little syntactic sugar.
精彩评论