tags:

views:

304

answers:

8
int a[A][B];
int* p = a[i];  //i<A-1

then what's the actual operation of the sentence below?

p++;
p+=B;
+14  A: 

p++ -> Go to next column in the matrix

p+=B -> Go to the next row (at the same column) in the matrix.

Naveen
A: 

The answer is quite simple if you draw the a[A][B] matrix in memory form, aka a vector and start with p pointing at the beginning of a[i] and then apply those operations.

Cristina
A: 

After the initialization, a has storage for A*B ints and p points to the B*i'th one (0-based). The later operations make it point to the B*(i+1)+1'th one.

ysth
One of those i's should be a 1.
mweerden
@mweerden: thanks
ysth
A: 
p = a[A-1]

is the same as

p = &a[A-1][0]

so

p++

results in

p == &a[A-1][1]

and then doing

p+=B

will result in

p == &a[A-1][1+B] == &a[A][1] // outside allocated memory
Jonathan Maddison
+5  A: 

For multidimensional arrays, one has to remember that the dimensions are applied from left to right, which makes it somewhat easier to visualise. for example:

int p[A][B][C];

This will be built as :

[][]--[][][][]--[][]_ _ _[][]--[][]   [][]--[][][][]--[][]_ _ _[][]--[][]
|---A----||---A----|     |---A----|---|---A----||---A----|     |---A----|
|---------------A*B---------------|   |---------------A*B---------------|
|---------------------------------A*B*C---------------------------------|

so if you have a p[i][j][k], i'ts actually (p+i+Bj+BCk)

Dasuraga
True, but you have A and C reversed in your illustration. Also, p+i+Bj+BCk should be p+BCi+Cj+k. In addition it is useful to note that adding v to p now gives you (p+v)+BCi+Cj+k which allows you to "distribute" v over i,j and k (keeping in mind that i<A, j<B and k<C).
mweerden
really? I always thought that [] operators were left->right processed. Shows what I know :P
Dasuraga
A: 
wrong. a[A][B] is contiguous memory. It is easy to verify this with a debugger, a memory viewer or a few simple printf statements.
abelenky
Yes, it is commonly contiguous as it's a simple optimization, but there is no guarantee. Therefore making the assumption that you can index past one pointer and have it properly index into the next is very dangerous. It's better to allocate your own single contiguous block of memory and index it accordingly.
Interesting points - does the standard guarantee contiguous allocation for multidimensional arrays? Anyone got a link?
Justicle
I've tried to find it as I was also under the impression that it was contiguous. However, I could not find any such guarantee in the standards of both C and C++.
mweerden
Not only do you have A and B flipped, they are *NOT* pointers.If you declare int a[A][B] there are no pointers involved. It is an array of B arrays-of-A-ints.There are no more pointers involved than there are in the case of int b[A].
Captain Segfault
Ok. I've had another look it is indeed (obviously) contiguous. See the first point of 6.2.5.20 of the C99 standard. An array is a contiguous block of elements, so an array of an array is a contiguous block of contiguous blocks of elements. @Captain Segfault: A and B are not "flipped" here (see 6.7.5.2).
mweerden
Recall that a[x][y] == *(a+A*x+y). This ONLY works if it is a contiguous set of memory. It is guaranteed.
abelenky
A: 

Just to further the conversation (although I can't actually respond to cbailey's post directly without enough reps...)

There's a big difference between declaring a multi-dimensional array on the stack, and on the heap.

As abelenky might be getting at, declaring a multi-dimensional array on the stack will always result in contiguous memory. I believe that the C standard actually states this somewhere, but even if it doesn't, every compiler on the planet will ensure that it is contiguous. Meaning that at the end of the day, you might as well be using a single dimension array, because the compiler will convert to that anyways.

In terms of being safe when using multi-dimensional arrays, regardless of whether they are allocated on the heap or the stack, you'd not want to iterate over them the way the original poster did.

mhughes
There is no difference w.r.t. stack or heap. The difference (concerning contiguous allocation) is in T[][] vs. T**. This is not the same as stack vs. heap as my T** can be on the stack and pointing to the stack (to pointers that also point to the stack) and I can easily allocate a T[][] on the heap. In fact, C "knows" nothing of stacks and heaps. B.t.w., the multidimensional arrays are indeed completely contiguous according to the standard (see my last comment to cbailey's post).
mweerden
A: 

This is sort of a meta-answer, aimed at much at Justicle as at the original poster.

Arrays degenerate into pointers, but they are not the same thing. Just because the syntax to get at a[3][7][1] is the same if a is a pointer-to-pointer-to-pointer-to-int versus an array-of-array-of-array-of-int doesn't mean that the actual operation is the same.

You can make an array of any type (of well defined size). Array dereference syntax and pointer syntax are the same, such that

a[i] == *(a+i) == i[a]

no matter what array type a is.

All the answers to questions in this thread can be derived from this.

int a[3][2][17];      //a is an array of length 17.
int (*b)[3][2] = a[5]; //b is a pointer to the fifth element of a
int (*c)[3] = b[1];    //c points to the first element of b.
b += 1; // b now points to the sixth element of a. (c is unchanged)
c += sizeof(*b); // c points to the first element of b again.

Note that none of this would work if a were not contiguous. If it didn't work then arrays of arrays would work differently than arrays of anything else.

Captain Segfault