tags:

views:

654

answers:

9

Hi, as a C newcomer I'm a bit confused about bidimensional arrays.

If I want to represent a matrix of 3 rows and 5 columns, I guess the correct declaration is:

char a[3][5];

So, is this an array of 3 pointers to 5 arrays of chars or what?

How come whenever I try to cycle through it like the following it seems to read the wrong results?

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<3; y++ ){
        printf( "%c", a[x][y] );
    }
}

Are the following equivalent and correct ways to initialize it?

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1},
               };

char a[3][5] = {1,0,0,0,1,
                1,0,0,0,1,
                1,0,0,0,1};

Thanks for any eventual upcoming explanation.


EDIT

Sorry the typos, the code is not copied. By the way, I keep on having them read like they where read in a vertical way, not in a horizontal one.

Also in the example in this tutorial http://www.cplusplus.com/doc/tutorial/arrays/ it reads the array in a way that is not streight-forward to me as it seems to work on a 5x3, Height*Width, y*x, cols*rows structure instead of a 3x5, Width*Height, x*y. rows*cols one:

#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];
int n,m;

int main ()
{
  for (n=0;n<HEIGHT;n++)
    for (m=0;m<WIDTH;m++)
    {
      jimmy[n][m]=(n+1)*(m+1);
    }
  return 0;
}
+2  A: 

You've got wrong results because you're using x twice (looks like a copy/paste error). Try

int x, y;
for (x = 0; x < 3; x++) {
    for (y = 0; y < 5; y++) {
        printf("%c", a[x][y]); // Emil H says "%d" might be more useful
    }
}

Edit: I'm not sure what's confusing about that tutorial. It's precisely equivalent to your code, except instead of printing the array, it's setting each element to (row*column) (where both row and column are one-based, hence the +1's).

Michael Myers
I think he'll want to use %d, since it isn't very useful to output null bytes. I typed the wrong sequence at first. Sorry about that. :)
Emil H
it's confusing the fact that generally width == x, height == y and he's declarying it like and reading it like [height][width] (or [y][x]) that is not really what i call a rows*cols structure but cols*rows
pistacchio
Thanks, pistacchio. I just saw that there was HEIGHT and WIDTH and didn't notice which was which dimension.
Michael Myers
A: 

You're using printf in the wrong way. Try:

printf("%d", a[x][y]);

I'm not sure whether you'll want to use %c or %d. If you want to print the number, use %d. If you want to print an actual character, use %c.

Emil H
+1  A: 
int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

You need to change the 2nd for loop to refer to 'y' instead of 'x'.

hope that helps.

Steve Lazaridis
+2  A: 

I see a couple of problems with your code. First (copied from above):

int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

In your inner-loop, it looks like you want to use y instead of x, and you want y to go from 0..5. Currently, you are repeating the variable x. Also, you have a problem with your printf() statement. Here's some corrected code:

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<5; y++ ){
        printf("%d\n", a[x][y] );
    }
}

Second, when you initialize your array, your code is almost correct. Here's the corrected version:

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1}
               };

(I removed the , after the very last "row" of data - that was a syntax error.)

The 2nd syntax you posted is incorrect (the one with no curly braces).

rascher
+1  A: 
danvin
but i don't the relation between the image and this:int jimmy [HEIGHT][WIDTH];it seems to me that a 3x5 structure is declared and accessed like a 5x3 structure. can you explain this, please?
pistacchio
It's a matter of how you want to access the arrays. If you turn the diagram sideways, you've got yourself the same array but now it's more like 3x5. If that makes more sense to you, you can draw your array representation diagram that way, it's still the same array.
danvin
A: 

char a[3][5];

So, is this an array of 3 pointers to 5 arrays of chars or what?

Yes, that's what it is. Although you could also manipulate it as a consecutive set of 15 chars.

By convention, most people would think of it as representing a matrix with 3 rows and 5 columns (I think), but there's nothing about the data structure itself that requires that. You could just as easily use it to represent 5 rows and 3 columns. Or 3 sets that each include 5 elements but have no meaningful relationship to each other at all.

A particular library for doing matrix manipulation would have a convention for this.

Dave Costa
There are no pointers. It's 15 bytes of data, organized into 3 groups of 5.
Robert
I can cast it to a pointer and access the data using that pointer, so conceptually I think it's reasonable to call it a pointer.
Dave Costa
In fact, I can use the array variable as a pointer to a pointer without even casting:int main( int argc, char** argv ) { char a[3][5] = { {0,1,2,3,4}, {5,6,7,8,9}, {10,11,12,13,14}, }; printf( "%d\n", **a );}So, I would call that a pointer. It's a constant pointer, of course.
Dave Costa
Dave, you can do that because there is an implicit conversion from an array to its first element. you can do the same with a function: *********************************main; is valid. But you would never say main is a pointer-pointer-pointer-....-pointer-to-function.
Johannes Schaub - litb
+4  A: 

Just for what it is and what not.

char a[3][5];

There are no pointers involved. A multi dimensional array like that is an array of arrays of .... and so on. In your case, you have an array of 3 arrays of 5 characters. It becomes clearer when you do it with typedefs.

typedef char T[5];
T a[3];

No pointers are involved whatsoever. If you want to access the first array of those 3 ones, you can do so:

a[0];

And it will give you back an object of type char[5]. Normally, you don't notice that because normally you index all dimensions. So the array that's returned by a[0] is subscript by the next index, for example a[0][1]. The [1] will be applied to the array that was returned by a[0], which as we have figured out earlier has type char[5].

So, is this an array of 3 pointers to 5 arrays of chars or what?

Let's create that type and see how it's different to the above. Creating it is simple, once you get the basic declarators:

  • Creating a pointer: *D
  • Creating an array: D[N]

D is just an existing another declarator. So now let's go on. First you say array of 3 pointers to 5 arrays of chars.... I think you meant array of 3 pointers to arrays of 5 chars. First, array of 5 is created like

D1[5]

Now, let's replace D1 by a pointer to declarator:

(*D2)[5]

We had to insert parentheses, because the subscript operator [N] binds better than the dereference operator *, and it would otherwise be read as *(D2[5]) which isn't what we want. Now we have pointer to array of 5.

Now let's do the array of 3. Replacing D2 by D3[3] yields this:

(*D3[3])[5]

Great, now we have got a array of 3 pointer to array of 5. Just putting the base type that that declarator appertains to yields the complete declaration:

char (*D3[3])[5];

That's of course a complete different thing :) You could use it to store pointers to your other array which was of type array of 3 arrays of 5 char. Let's store a pointer to the first sub-array of a into D3[0]. We figured out earlier that a[0] has type char[5]. We can store a pointer to that array into D3[0], because D3 is an array of pointers to char[5], what a coincidence!

D3[0] = &a[0]; // works!

I hope this little exercise has shown you some of the relations between pointers and arrays. Cheers!

Johannes Schaub - litb
+1  A: 

The small errors like using "%c" when you probably want "%d" and such are not what you really want to get answered I humbly think. You say you are a bit confused about arrays and also mentions that you expect to see pointers as the array-elements of the array containing arrays. You

The last comma in your definition of the array-of-arrays is NOT a syntax error. It is permitted as of C99.

What really will clear up things is to know that arrays are not pointers. It is true that an array name may be used as a constant pointer (to the first element) and that pointers can be indexed like they were arrays. This does not mean, however, that arrays and pointers are the same. They are not.

You ask about what the symbol "a" in your program actually is. It is an array of arrays. The memory layout may be visualized like a long line cut in three parts but still on a continuous line. Then cut each of these in five parts in the same manner. When addressing one element you must use two indexes; first for which five-element-array you want and then for which fifth of this element you want.

The memory layout is not like a grid of rows and columns. The memory is addressed by one scalar, so its linear. Pointer arithmetic may be the next thing you could look into, and see how an increment on a pointer works.

hept
A: 

hept:

You ask about what the symbol "a" in your program actually is. It is an array of arrays. The memory layout may be visualized like a long line cut in three parts but still on a continuous line. Then cut each of these in five parts in the same manner. When addressing one element you must use two indexes; first for which five-element-array you want and then for which fifth of this element you want.

so, the counter-intuitive way of accessing my 3x5 (width x height) grid (or an array of 3 parts of 5 units) is to declare it like a width*height array and access it like a height*width?

pistacchio