2d array dynamically allocation ..

Started by
2 comments, last by Zahlman 13 years, 6 months ago
Hi,

I think a[j] is being calculated by computer by assuming all rows are stored in a continuous manner , with no gaps between them .Ofcourse , individual elements in each row are also stored sequentially .

then why this code works .. here rows are not stored directly after one other ..


#include<iostream>using namespace std;int main(){ int rows = 3; int cols = 4; int** a = (int**)malloc(rows*sizeof(int*));  for(int i =0 ;i<rows;i++){ a = (int*)malloc(cols*sizeof(int));}for(int i = 0 ; i<rows;i++){ cout<<"\n"; for( int j = 0 ;j < cols;j++) { cout<<&a[j]<<" "; }}for(int i = 0 ; i<rows;i++){ cout<<"\n"; for( int j = 0 ;j < cols;j++) { a[j] = i+j; }}cout<<"\n********************88\n";for(int i = 0 ; i<rows;i++){ cout<<"\n"; for( int j = 0 ;j < cols;j++) { cout<<a[j]<<" "; }}}


output is


0x8051468 0x805146c 0x8051470 0x8051474
0x8051498 0x805149c 0x80514a0 0x80514a4
0x80514c8 0x80514cc 0x80514d0 0x80514d4



********************88

0 1 2 3
1 2 3 4
2 3 4 5


please someone explain >>

[Edited by - Zahlman on October 16, 2010 4:42:59 PM]
Advertisement
In this case, and someone correct me if I'm wrong, I believe it has to do with the way C and C++ handle the indices. In your code you have
a[j]

which can be turned into
(a)[j]

or rather, get the pointer stored in a, then go along a to the j-th location. It's not that C++ is treating the memory as contiguous, but you always refer to a as having two dimensions. In this case, if you were to refer to it as a[x], then once you got past the first row, you'd be in trouble.

I would rather use a picture to explain it, but I don't have a good one to hand.

If you asked for all 'a' addresses, you'd probably see that they were contiguous, but instead, you ask for the address stored in 'a' to get the address at the j-th offset.

Sorry if that still doesn't help. It's making sense in my head, but I seem to be having trouble explaining at the moment.
Sidenote: if using C++ (which you are; iostream is a c++ only header) then I strongly recomment you drop malloc and use new/delete/new[]/delete[]. malloc will work for ints, but once you start using classes you'll want the C++ memory allocators.

webwraith seems to have it. Just remember that you are allocating two different things. A contiguous array of pointers, with the first pointer being pointed at by the variable 'a'. And then a series of arrays of int, each array of int being pointed at by one of the elements from the array of pointers.

The syntax used is just a byproduct of the way arrays resolve to one less level of indirection along with operator chaining. You can do array[a1][a2]...[an] for every '*' you made when you declared array. i.e. if you had int **** array; you can chain array subscripts up to 4 times until you reach zero levels of indirection away from 'int'.

And if that didn't help, maybe an analogy will. Imagine you want to write out all of housing addresses for a row of streets. You could just do a table of all the addresses in a nice grid. Or you could have it so each street name had a list of addresses and then you would keep a seperate list of street names. The list of street names corresponds to the array of pointers. And each list of streets having its own list of addresses corresponds to the series of array of int.

Then there are higher level things to take under consideration. Rather than using any direct memory allocation consider std::vector or boost::multi_array if feasible.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by y2jsave
I think a[j] is being calculated by computer by assuming all rows are stored in a continuous manner


Nitpick: you mean contiguous. :) This is a fairly special term that you won't see much outside of computer science, though.

Anyway, a[i][j] is always calculated by applying [i] to a, and then applying [j] to the result of that. What that means depends on the type of a.

When 'a' is a two-dimensional static array, the index is calculated the way you describe. That works because 'a' is actually an array of arrays, so that [i] selects one of the "row" arrays, and then [j] selects an element. Arrays are not pointers; they merely 'decay' to pointers very easily. Internally, the compiler writes code to multiply the value of 'i' by the size of a row to figure out the offset from the beginning of the array to the desired row; then multiply the value of 'j' by the size of the elements to find the offset from the beginning of the row to the desired element; and each of these values gets added to the address of the beginning of the array. (When 'i' and 'j' are constant, the compiler will then, normally, notice that the math can be done ahead of time, and just supply a constant value to add to the array's location.)

When 'a' is a pointer to dynamically allocated memory, as in your case, applying [i] yields an element from the dynamic allocation. In your case, that element is another pointer to dynamically allocated memory, and [j] does the same thing to find the actual array element.

This topic is closed to new replies.

Advertisement