quick 2-dimensional array question in C

Started by
14 comments, last by shizik 22 years, 5 months ago
Or you could write func() like this:

  void func (int** arr, int x, int y){        for(int i = 0; i < x; ++i)    {        for(int j = 0; j < y; ++j)	    arr[i][j] = i * j;    }}  


And not have to worry about the i*y + j shiznit.

I''m pretty sure Oluseyi is right on this one. Sure you could do it the other way, but why would you want to?? This is much more clear. Plus if you are passing a 2D array to the other version then you might (I''m not sure) get a type warning/error, and you might have to cast the 2D array (int**) to a 1D array (int*).

And we haven''t even begun to get into semantics..

But whatever...
--------------------------I guess this is where most people put a famous quote..."Everything is funnier with monkey''s" - Unknown
Advertisement
quote:Original post by Promiscuous Robot
Plus if you are passing a 2D array to the other version then you might (I''m not sure) get a type warning/error, and you might have to cast the 2D array (int**) to a 1D array (int*).


quote:From my earlier post of the compiler output:
d:\microsoft visual studio\arr_ptr.cpp(25) : error C2664:	''function'' : cannot convert parameter 1 from ''int [10][12]'' to ''int *'' 


He''s absolutely right. Which, of course, means that I''m absolutely right :D.

Also, about using std::vector, the case is even more restrictive there. To declare and use a 2D vector you''d do this:
typedef vector<vector<int> > doublevec_int; // for conveniencedoublevec_int arr;  //void function(vector<int> &v){  ...    v[j * y + k] = j * k;  ...} 

The code above won''t even compile, and I don''t even need to pass it through my compiler to know that. Levels of indirection are very specific in C/C++, and are an integral part of the language. They''re absolutely not interchangeable.
quote:Original post by Promiscuous Robot
Or you could write func() like this:
void func (int** arr, int x, int y){        for(int i = 0; i < x; ++i)    {        for(int j = 0; j < y; ++j)	    arr[ j ] = i * j;<br>    }<br>}<br>  </pre>        <br>And not have to worry about the i*y + j shiznit.<br>  <hr height=1 noshade></SPAN></BLOCKQUOTE>        <br><br>Perhaps not, but as I keep saying you can't pass that function a 2-dimensional array and expect it to work:<br><br><pre><br>// with func() defined by Promiscuous Robot<br>int main()<br>{<br>    int a[20][20];<br>   <br>    func(a,20,20);        // won't compile<br><br>    func((int**)a,20,20); // won't work<br><br>    return 0;<br>}<br>  </pre>          <br><br>In order to get the int** parameter to work as you expect, you'd have to construct an array of pointers to integers:<br><br><pre><br>// with func() defined by Promiscuous Robot<br>int main()<br>{<br>    int *a[20];<br>    <br>    for(int i = 0; i < 20; ++i)<br>        a = new int[20];<br>    <br>    func(a,20,20); <br><br>    return 0;<br>}<br>          </pre>          <br><br>That will work, and while it's a valid technique the parameter to func() is not a 2-dimensional array anymore. In order to avoid the minor syntactic inconvenience of "the i*y + j shiznit" you require the caller to rearrange his data structures - which may be trivial, non-trivial, or even impossible depending on the circumstances.<br><br><BLOCKQUOTE><SPAN CLASS=smallfont>quote:<hr HEIGHT=1 noshade>Original post by Oluseyi<br>Also, about using std::vector, the case is even more restrictive there. To declare and use a 2D vector you'd do this:<br><pre><br>typedef vector<vector<int> > doublevec_int; // for convenience<br>doublevec_int arr;  <br>void function(vector<int> &v)<br>//<br>{<br>  …<br>  v[j * y + k] = j * k;<br>  …<br>} <br>  </pre>   <br>The code above won't even compile, and I don't even need to pass it through my compiler to know that.<br>   <hr height=1 noshade></SPAN></BLOCKQUOTE>          <br><br>I've never stated you could (or should) do anything like that; that's just silly.<br><br><BLOCKQUOTE><SPAN CLASS=smallfont>quote:<hr HEIGHT=1 noshade><br>Levels of indirection are very specific in C/C++, and are an integral part of the language. They're absolutely not interchangeable.<br>         <hr height=1 noshade></SPAN></BLOCKQUOTE>          <br><br>Which is pretty much what I've been saying all along. There's a big difference between a 2-dimensional array and anything you can pass to func() as an int**.<br><br><br><br>Edited by - spock on November 20, 2001 2:13:30 AM    
Ummmmm. I need to know this too. Is it possible or not?
Using gamedev's search with the words "multi" and "array", this ground has been covered in many places:
http://www.gamedev.net/community/forums/topic.asp?topic_id=53204
http://www.gamedev.net/community/forums/topic.asp?topic_id=51897
http://www.gamedev.net/community/forums/topic.asp?topic_id=63234

What it comes down to is that there are three ways to do multi-dimensional arrays:
- use an auto C array: int array[5][6][10].
- allocate a single block of memory and do the math of the dereferencing yourself (or write a class to do it).
- allocate multiple blocks in a loop; e.g. for a 2-d int array, you'd allocate col# of int*, then for each of those row blocks you allocate row# of int. This fragments memory and has more memory overhead than the prior example, but it gives you "natural" multi-dim. array semantics (e.g. array[3][5] will do the right thing). This method can also be extended to n dimensions, but requires n-1 loops to allocate/deallocate.

To pass these arrays into functions, you have to know the type. For the second type of array, you will have a Type* regardless of the dimensions you're faking because it was allocated to it. If you use the third type of array, you will have a Type** or Type***, where the number of # is the number of dimensions.

If you want to pass the first array into a function, e.g. int array[5][6][10], its type is int [][6][10]. This means that all but one dimension of the array must be nailed down by the function prototype in order to make it work; if you understand that C internally treats this array as a single block of memory, this should make sense.

If your function is going to work on arrays where the size of all but the first dimension are known, this is fine. If you need your function to work for arbitrary N-dimensional arrays, you need to choose one of the other methods listed above.

Edited by - Stoffel on November 21, 2001 1:04:38 PM
Urgh. That looks nasty! Anyway, I got it sorted out a solution, which uses just a big 1d array, which the code can treat like a 2d array. I just cant believe C doesnt let do something like (without typecasting, etc.):

int array[10][10];
func(&array);

void func(int *array) {
...
}


Edited by - Ibanez on November 21, 2001 5:36:58 PM

This topic is closed to new replies.

Advertisement