Author Message
 westco
 Posted: Jun 15, 2012 - 02:41 AM
 Joined: May 09, 2009 Posts: 113
 I have a question regarding two-dimensional arrays. When trying to access a two-dimensional array with pointer arithmetic the following is used: *(*(array_name + row) + column) Example: Code: int B[2][2] = {4, 5, 6, 7}; printf("B = #p\n", B);               // address of B[0][0] printf("&B = #p\n", &B);           // address of B[0][0] printf("B+1 = #p\n", B+1);       // address of B[1][0] printf("B[0][0] = #d\n", B[0][0]); // content of B[0][0] = 4 printf("B[0] = #p\n", B[0]);        // address of B[0][0] printf("*B = #p\n", *B);             // address of B[0][0] printf("**B = #d\n", **B);        // content of B[0][0] = 4 printf("**(B+1) = #d\n", **(B+1)); // content of B[1][0] = 6 printf("**B+1 = #d\n", **B+1);     // content of B[0][1] = 5 printf("**B+3 = #d\n", **B+3);     // content of B[1][1] = 7                 # = % in above code to get around the Bad Request Error I have a hard time understanding this. Why does it take (2) de-references to get the content of the specific array element? Can someone explain how this works? Last edited by westco on Jun 15, 2012 - 07:45 AM; edited 9 times in total

 jwatte
 Posted: Jun 15, 2012 - 04:42 AM
 Joined: Apr 28, 2012 Posts: 70
 We have to see the declaration of array_name to make sense of it. My guess: array_name is declared as "something **array_name"

 stevech
 Posted: Jun 15, 2012 - 04:57 AM
 Joined: Dec 18, 2001 Posts: 4717
 Quote: *(*(array_name + row) + column) That's awful code and invalid, I say.

 ChaunceyGardiner
 Posted: Jun 15, 2012 - 05:30 AM
 Joined: Mar 09, 2012 Posts: 1452 Location: North Carolina, USA
 stevech wrote: Quote: *(*(array_name + row) + column) That's awful code and invalid, I say. I don't like it either, but it looks valid to me. (Assuming array_name is a **)

 ChaunceyGardiner
 Posted: Jun 15, 2012 - 05:41 AM
 Joined: Mar 09, 2012 Posts: 1452 Location: North Carolina, USA
 westco wrote: I have a question regarding two-dimensional arrays. When trying to access a two-dimensional array with pointer arithmetic the following is used: *(*(array_name + row) + column) I have a hard time understanding this. Why does it take (2) de-references to get the content of the specific array element? Can someone explain how this works? Rather than explain how that works, I'll tell you how I'd write it: Code: array_name[row][column] I would have to see the array declaration and do some testing to be sure that's the same, but I think it will work.

 mnehpets
 Posted: Jun 15, 2012 - 06:16 AM
 Joined: Nov 09, 2011 Posts: 402
 It's one of these weirdo C-isms. Let's say you have an array declared thusly: Code: int z[10][4]; This declares z to be a 10 row array. Each row of this array is an array of 4 ints. Dereferencing z once gives you a value that's one of the rows of z, so it's one of the 4 element int arrays, or equivalently an int pointer (recall that in C, int pointers and int arrays are sorta interchangable). This is how we assign zp to the 2nd row of z: Code: int z[10][4]; int *zp = *(z + 2); Since zp is now a regular garden variety pointer, dereferencing zp gives you an int. Thus, to get the third int value in the second row of z we do: Code: int z[10][4]; int *zp = *(z + 2); int y = *(zp + 3); We can combine the two dereferences in a single statement: Code: int z[10][4]; int y = *(*(z + 2) + 3); - S ps: observant folks will note that I'm assigning y from an uninitialised value.

 Koshchi
 Posted: Jun 15, 2012 - 06:29 AM
 Joined: Nov 17, 2004 Posts: 13849 Location: Vancouver, BC
 Quote: I would have to see the array declaration and do some testing to be sure that's the same, but I think it will work. I don't think so. array_name is an address of the start of the array, (array_name + row) is the address of an element of the array. *(array_name + row) is the value of the array element. In order for adding column to that value to make sense, it would have to be another pointer, and therefore array_name must be an array of pointers to arrays, not a straight two dimensional array. In order to access a two dimensional array with pointer arithmetic, you need to know the size of the array (or at least the number of columns). _________________Regards, Steve A. The Board helps those that help themselves.

 westco
 Posted: Jun 15, 2012 - 07:46 AM
 Joined: May 09, 2009 Posts: 113
 I added an example to the original post.

 mnehpets
 Posted: Jun 15, 2012 - 08:01 AM
 Joined: Nov 09, 2011 Posts: 402
 westco wrote: Code: int B[2][2] = {4, 5, 6, 7}; printf("B = #p\n", B);               // address of B[0][0] printf("&B = #p\n", &B);           // address of B[0][0] printf("B+1 = #p\n", B+1);       // address of B[1][0] printf("B[0][0] = #d\n", B[0][0]); // content of B[0][0] = 4 printf("B[0] = #p\n", B[0]);        // address of B[0][0] printf("*B = #p\n", *B);             // address of B[0][0] printf("**B = #d\n", **B);        // content of B[0][0] = 4 printf("**(B+1) = #d\n", **(B+1)); // content of B[1][0] = 6 printf("**B+1 = #d\n", **B+1);     // content of B[0][1] = 5 printf("**B+3 = #d\n", **B+3);     // content of B[1][1] = 7                 The comments in the last 2 examples aren't right. What's happening is that the "*" dereference operator has higher precedence than the "+" operator. So, Code: **B+1 is the same value as Code: (**B) + 1 which is the same value as B[0][0] + 1 - S

 ChaunceyGardiner
 Posted: Jun 15, 2012 - 08:59 AM
 Joined: Mar 09, 2012 Posts: 1452 Location: North Carolina, USA
 Koshchi wrote: Quote: I would have to see the array declaration and do some testing to be sure that's the same, but I think it will work. I don't think so. array_name is an address of the start of the array, (array_name + row) is the address of an element of the array. *(array_name + row) is the value of the array element. In order for adding column to that value to make sense, it would have to be another pointer, and therefore array_name must be an array of pointers to arrays, not a straight two dimensional array. Who said it was a two-dimensional array ? In order to make sense out of the posted code, I assumed the array was declared a **. The posted notation is a stupid way to do it anyway. And like I said, I would like to see the array declaration at hand. Now he's thrown in a [][] declaration, which makes the posted notation even more stupid - and my suggestion will still work.

 JohanEkdahl
 Posted: Jun 15, 2012 - 09:13 AM
 Joined: Mar 27, 2002 Posts: 18585 Location: Lund, Sweden
 ChaunceyGardiner wrote: Who said it was a two-dimensional array ? In the very first post, perhaps edited in, westco wrote: I have a question regarding two-dimensional arrays. [...] Code: int B[2][2] = {4, 5, 6, 7};

 ChaunceyGardiner
 Posted: Jun 15, 2012 - 09:50 AM
 Joined: Mar 09, 2012 Posts: 1452 Location: North Carolina, USA
 JohanEkdahl wrote: ChaunceyGardiner wrote: Who said it was a two-dimensional array ? In the very first post, perhaps edited in, westco wrote: I have a question regarding two-dimensional arrays. [...] Code: int B[2][2] = {4, 5, 6, 7}; If you read the rest of the post of mine that you quoted you should be able to deduce that he did indeed throw that in later. And my suggestion should work for that too, so...

 clawson
 Posted: Jun 15, 2012 - 11:33 AM
 Joined: Jul 18, 2005 Posts: 62354 Location: (using avr-gcc in) Finchingfield, Essex, England
 Not sure what your intention here is exactly but does it help to know that if you use: Code: int (*foo)[2] = (int (*)[2])B; then you can just use the same array notation with foo. That is: Code: foo[1][1] = 9; This allows you to pass around a multi-dim array pointer then just continue to access it as a multi-dim array. For example: Code: void process(int (*alsodata)[2][2]) {    uint8_t i,j,k;    for (i=0; i<3; i++) {       for(j=0; j<2; j++) {          for(k=0; k<2; k++) {             alsodata[i][j][k] += 1;          }       }    } } int main(void) {    int data[3][2][2] = {       {{4,7}, {5,3}},       {{2,9}, {4,8}},       {{5,6}, {6,1}},    };    process((int (*)[2][2])data); } Of course process() could just as easily be: Code: void process(int alsodata[3][2][2]) {    uint8_t i,j,k;    for (i=0; i<3; i++) {       for(j=0; j<2; j++) {          for(k=0; k<2; k++) {             alsodata[i][j][k] += 1;          }       }    } } but if you just have an int * pointer and want to apply a multi-dim interpretation onto it the former is the way to go: Code: void process(int * p) {    int (*alsodata)[2][2] = (int (*)[2][2])p;    uint8_t i,j,k;    for (i=0; i<3; i++) {       for(j=0; j<2; j++) {          for(k=0; k<2; k++) {             alsodata[i][j][k] += 1;          }       }    } } int main(void) {    int data[3][2][2] = {       {{4,7}, {5,3}},       {{2,9}, {4,8}},       {{5,6}, {6,1}},    };    process((int *)data); } in which alldata reinterprets the plain int pointer that was passed. _________________

 westco
 Posted: Jun 15, 2012 - 04:27 PM
 Joined: May 09, 2009 Posts: 113
 Thanks for all the posts on this. I am not really interested in knowing all the other ways of doing this. I want to know how the original posts arithmetic pointer's work to access a two-dimensional array. Does anybody understand the example code in the original post? Is this true: *(*(array_name + row) + column) Why does one need two de-references to access the content of the array element?

 Visovian
 Posted: Jun 15, 2012 - 05:21 PM
 Joined: Aug 07, 2007 Posts: 1477 Location: Czech
 Code: x = *(*(array_name + row) + column) x =   *(array_name + row) + column I did some tests and I am a little confused. How is it possible that both lines give the same (and right) result ?

 ChaunceyGardiner
 Posted: Jun 15, 2012 - 07:15 PM
 Joined: Mar 09, 2012 Posts: 1452 Location: North Carolina, USA
 westco wrote: Is this true: *(*(array_name + row) + column) Not sure what you mean when you say "is this true" but... Code: A = array_name; B = *(A + row); // A must be a pointer or array for this to work C = *(B + column); // B must be a pointer or array for this to work So for you to be able to use this to access C as you do in your example, it follows that A must be a |pointer to or array of| some |pointers to or arrays of| some type.

 jayjay1974
 Posted: Jun 16, 2012 - 01:41 AM
 Joined: Oct 30, 2002 Posts: 5720 Location: The Netherlands
 Quote: Is this true: *(*(array_name + row) + column) Yes. See here The a[b] notation is just syntactic sugar for *(a+b). So... a[row][col]=(*(a+row))[col]=*(*(a+row)+col)) And... for laughs: Code: int arr[10]; (arr+2)[3]=5["abcdefg"]; Is perfectly legal and working C

 jwatte
 Posted: Jun 16, 2012 - 07:51 AM
 Joined: Apr 28, 2012 Posts: 70
 Visovian wrote: Code: x = *(*(array_name + row) + column) x =   *(array_name + row) + column I did some tests and I am a little confused. How is it possible that both lines give the same (and right) result ? No, those lines are not equivalent. If array_name is a double-array or pointer-to-pointer, the type of the first line is element, but the type of the second line is pointer. The only case where those lines are equivalent would be where "x" and "*x" have the same value, which certainly is possible if the item at address X happens to also have the value X. The double-array also makes sense if you pick it apart one step at a time: Code: unsigned int foo[3][7] = ...; This reads, inside-out, right-before-left, as "foo is an array of 3 arrays of 7 unsigned ints." Thus, once you dereference it once, you end up with "array of 7 unsigned ints." When you dereference it a second time, you end up with "unsigned int." Generally, C declarations are read inside-out, first right, then left. The main trick here is that you peel off only one thing at a time, both when writing the declaration, and when reading it, and when using it.

 Visovian
 Posted: Jun 16, 2012 - 04:13 PM
 Joined: Aug 07, 2007 Posts: 1477 Location: Czech
 Quote: The only case where those lines are equivalent would be where "x" and "*x" have the same value, You are right. It was the case, thanks.

 Display posts from previous:  All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 Jump to: Select a forum Forum index|--[AVR (8-bit) Technical Forums]|   |-- AVR forum|   |-- XMEGA forum|   |-- AVR Wireless forum|   |-- AVR GCC forum|   |-- AVR Studio 5 and Atmel Studio 6 forum|   |-- AVR studio 4 forum|   |-- AVRfreaks Academy forum|   |-- AVR Tutorials|--[AVR Software Framework]|   |-- AVR Software Framework|--[AVR32 (32-bit) Technical Forums]|   |-- AVR32 Linux Forum|   |-- AVR32 General (standalone)|   |-- AVR32 Software Tools|   |-- AVR32 Hardware|--[General Electronics Technical Forums]|   |-- General Electronics|   |-- Atmel Security Products|--[Non-technical forums]|   |-- AVRfreaks.net Housekeeping|--[Non-topical forums]|   |-- Off-topic forum|   |-- AVRfreaks Trading Post
All times are GMT + 1 Hour