Help: Pointer to 2-D array of structs.
Author |
Message |
beach9.. #1 / 12
|
Help: Pointer to 2-D array of structs.
Hello. I'm having trouble trying wrapping my head around this problem in C: 1) I have a struct defined typedef struct { double a, b, c; } Triple; 2) and I use it in a two-dimensional context with multiple instances: Triple array1[3][2] = { { {0.5, 0.0, 0.0}, {0.0, 0.0, 0.0} }, { {0.0, 0.5, 0.0}, {0.0, 0.0, 0.0} }, { {0.0, 0.0, 0.5}, {0.0, 0.0, 0.0} } }; ... Triple arrayN[3][2] = { { {1.5, 1.0, 1.0}, {1.0, 1.0, 1.0} }, { {1.0, 1.5, 1.0}, {1.0, 1.0, 1.0} }, { {1.0, 1.0, 1.5}, {1.0, 1.0, 1.0} } }; 3) Now, later on in the code I would like to create a pointer to point to one of the arrays depending on a flag: Triple *p; if (flag == ARRAY1) { p = array1; } ... if (flag == ARRAYN) { p = arrayN; } The Questions are 1) how do I declare the pointer (is it Triple **p, or Triple *p or ...) 2) how do I assign the pointer to the reference of the array (is it p = &array1 or p = &(array1[0] or ...) 3) how do I access the information with the pinter (is it (*p)[2][1] or p[2][1] or...) Thanks for your help. E.B. --
|
Thu, 10 Jul 2003 13:22:57 GMT |
|
|
Jim Fische #2 / 12
|
Help: Pointer to 2-D array of structs.
Quote: > The Questions are > 1) how do I declare the pointer (is it Triple **p, or Triple *p or ...)
In the following examples, the identifiers 'r' and 'c' are compile-time constant expressions -- i.e., their exact values are known by the compiler when the code is translated (e.g., const int r = 23; etc.); their values are NOT assigned at run time. Given the array declaration, X a[r] the array 'a' is a 1-D array comprised of 'r' elements of type 'X'. If you want to store the address of the a's first element (i.e., a[0]) in a pointer variable, you would write, X* p; // Load into 'p' the address of the type X object that resides at // index 0 (zero) within the array object 'a' p = &a[0]; // or, p = a; // <- this is just a synonym for '&a[0]' also, p = &a[1]; // 'p' points at the X object at index 1 in 'a' p = &a[2]; // 'p' points at the X object at index 2 in 'a' ... Given the array declaration, X a[r][c] the array 'a' is a 1-D array comprised of 'r' elements of type 'X[c]'. In other words, each element in the 1-D array 'a' is itself a 1-D array object comprised of a total of 'c' type X objects. If you want to store the address of the a's first element (i.e., a[0]) in a pointer variable, you need to note that a[0] is an array object and NOT a singleton type X object (as in the previous example). So you would write, X (*p)[c]; // 'p' is a pointer to an X[c] object // Load into 'p' the starting address of the 'X[c]' object that // resides at index 0 (zero) in array 'a' p = &a[0]; // or p = a; // <- this is just a synonym for '&a[0]' also, p = &a[1]; // 'p' points to the X[c] object at index 1 in 'a' p = &a[2]; // 'p' points to the X[c] object at index 2 in 'a' ... Now note what happens when you apply the array indexing operator '[]' to the pointer variable 'p': p[0] points to a[0] p[1] points to a[1] p[2] points to a[2] ... p[r-1] points to a[r-1] Since a[0] is itself an X[c] array object (i.e., an c-element array of X objects), you can apply the array indexing operator to 'p' a second time to obtain a specific type X object within the specified X[c] array object: p[0][0] points to a[0][0] p[0][1] points to a[0][1] p[1][0] points to a[1][0] ... p[r-1][c-1] points to a[r-1][c-1] Now for the mind blower: p = &a[2]; // 'p' points to the X[c] object at index 2 in 'a' p[0][5] points to ?? /* ans: a[2][5] */ p[1][0] points to ?? /* ans: a[3][0] */ p[2][2] points to ?? /* ans: a[4][2] */ ... In your particular case, you'd have, Tripple array1[3][2] ... Tripple (*p)[2]; // 'p' is a pointer to a 'Tripple[2]' object p = &array1[0]; // or, p = array1; // <- a synonym for '&array1[0]' p[0] points to 'array1[0]' p[0][0] points to 'array1[0][0]' p[2] points to 'array1[2]' p[2][1] points to 'array1[2][1]' ... p[1][2].a = 2.71828; // array1[1][2].a = 2.71828; p[1][2].b = 3.14159; // array1[1][2].b = 3.14159; p[1][2].c = 0.0; // array1[1][2].c = 0.0 p = &array1[2]; // 'p' points to the Tripple[2] object at // index 2 in 'array1', so... p[0][0] // points to 'array1[2][0]' p[0][0].a = 1.23; // assigns 1.23 to 'array1[2][0].a' Jim --
|
Fri, 11 Jul 2003 01:29:55 GMT |
|
|
Robert J. Hanse #3 / 12
|
Help: Pointer to 2-D array of structs.
Quote: > The Questions are > 1) how do I declare the pointer (is it Triple **p, or Triple *p or ...) > 2) how do I assign the pointer to the reference of the array (is it p = > &array1 or p = &(array1[0] or ...) > 3) how do I access the information with the pinter (is it (*p)[2][1] or > p[2][1] or...)
All of the following are equivalent (or, rather, conversions between all of them are trivial): Foo **ppFoo Foo *pFoo[X] Foo Foo[X][Y] I know this is confusing--hopefully, a sample will help make things clear. Remember that it's 3:00am as I write this, I'm dead tired, and that means this code might very well be wrong. :) Don't let the inline variable definition in the for loop throw you--this is just pseudocode. char *pFoo[4] = { "String 1", "String 2", "String 3", NULL Quote: };
char **ppFoo = pFoo; /* or, char **ppFoo = &pFoo[0], it's all the same */ while (ppFoo) { printf("%s\n", **ppFoo); ppFoo++; Quote: }
for (int i = 0 ; i < 3 ; i++) printf("%s\n", *pFoo[i]); --
|
Fri, 11 Jul 2003 01:30:33 GMT |
|
|
Serge #4 / 12
|
Help: Pointer to 2-D array of structs.
Quote: > > The Questions are > > 1) how do I declare the pointer (is it Triple **p, or Triple *p or ...) > > 2) how do I assign the pointer to the reference of the array (is it p = > > &array1 or p = &(array1[0] or ...) > > 3) how do I access the information with the pinter (is it (*p)[2][1] or > > p[2][1] or...) > All of the following are equivalent (or, rather, conversions between all of > them are trivial): > Foo **ppFoo > Foo *pFoo[X] > Foo Foo[X][Y]
Given that you post to C groups, the last expression is Error : X redefinition. As of their being identical. Let's rewrite this: char **ppchar; char *apchar[5]; char aachar[5][6]; If on a given machine the size of a pointer is 4 then sizeof (ppchar) == 4 sizeof (apchar) == 20 sizeof (aachar) == 30 As of conversions, the only trivial conversion is from apchar to ppchar. The conversion from aachar to ppchar is possible though it would be considered suspicious by any decent C compiler. Other conversions, from ppchar to apchar, from ppchar to aachar, from apchar to aachar, from aachar to apchar, are all illegal and would be Error : conversion to array type is illegal. Quote: > I know this is confusing--hopefully, a sample will help make things clear. > Remember that it's 3:00am as I write this, I'm dead tired,
You'd better sleep, buddy. Quote: > and that means > this code might very well be wrong. :) Don't let the inline variable > definition in the for loop throw you--this is just pseudocode. > char *pFoo[4] = > { > "String 1", > "String 2", > "String 3", > NULL > }; > char **ppFoo = pFoo; > /* or, char **ppFoo = &pFoo[0], it's all the same */ > while (ppFoo) > { > printf("%s\n", **ppFoo); > ppFoo++; > } > for (int i = 0 ; i < 3 ; i++) printf("%s\n", *pFoo[i]);
Ok let it be defined "in the for loop". What about type mismatch in your expressions. "%s" in the format string suggests that you were trying to pass a string (char *). Both **ppFoo and *pFoo[i] are char's. Sergei --
|
Fri, 11 Jul 2003 12:28:24 GMT |
|
|
Robert J. Hanse #5 / 12
|
Help: Pointer to 2-D array of structs.
Quote: > As of their being identical. Let's rewrite this:
At no time did I say they were identical, merely that equivalencies existed. Quote: > As of conversions, the only trivial conversion is from apchar to ppchar. > The conversion from aachar to ppchar is possible though it would be > considered suspicious by any decent C compiler.
Err, you mean it's not possible to do ppchar = (char **)&aachar[0][0] ? :) Granted, it's 4:15am and I'm very tired yet again, but something seems not quite right there if such a cast is forbidden. Or even if it flags a warning. Quote: > Other conversions,
I said conversions were trivial, not that they could be done exclusively via a simple cast. Transforming a double-pointer into a two-dimensional array of characters is a trivial exercise in programming. Quote: > from ppchar to apchar,
Let me get this straight. You're saying that if I dereference ppchar, it *won't* give me a valid pointer? :) char **ppchar; char *apchar[X]; ppchar = apchar; .... If I dereference ppchar once (*ppchar), it'll give me the pointer stored in apchar[0]. If I dereference ppchar twice (**ppchar), it'll give me the value of the pointer which *ppchar points to--or equivalent to saying *(apchar[0]). Seems like there's an equivalence there. Quote: > Ok let it be defined "in the for loop". What about type > mismatch in your expressions. "%s" in the format string > suggests that you were trying to pass a string (char *). > Both **ppFoo and *pFoo[i] are char's.
If that's the only error I made in the pseudocode, then I must be less tired at 3:00am than I think :) Insofar as inline variable declaration, that's an extremely common C++ism; I'm surprised you haven't seen it before. Just to make sure I'm not totally barking mad, here's a quick program I just typed in. 1 /* file pointertest.c */ 2 #include<stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 char **ppchar, **ppchar2; 7 char *apchar[5]; 8 char aachar[5][5]; 9 10 ppchar = &apchar[0]; 11 ppchar = (char **) &aachar[0][0]; 12 ppchar = (char **) malloc(sizeof(char *) * 5); 13 ppchar2 = (char **) malloc(sizeof(char *) * 5); 14 15 for (i = 0 ; i < 5 ; i++) 16 { 17 *ppchar = apchar[i]; 18 ppchar++; 19 } 20 21 for (i = 0 ; i < 5 ; i++) 22 { 23 *ppchar2 = &aachar[i][0]; ppchar2++; 24 } 25 26 return 0; 27 }
.... GCC 2.95 doesn't flag any warnings or errors, nor does Red Hat's peculiar GCC 2.96. In line 10, we establish that conversions between doublepointers and arrays of pointers are possible; in 11, we establish the same between doublepointers and 2-D arrays. In lines 15-19, we trivially turn an array of pointers into a properly arranged doublepointer. In lines 21-24, we trivially convert a 2-D array into a properly arranged doublepointer. But then again, maybe I'm smoking crack. But if I am, then GCC is on the pipe, too. --
|
Sat, 12 Jul 2003 02:40:14 GMT |
|
|
Robert J. Hanse #6 / 12
|
Help: Pointer to 2-D array of structs.
When I was adding the line numbers to the source code, I accidentally deleted an "int i" that should've gone after the declaration of aachar[5][5]. My goof. If there are any other bugs that I added in while adding in line numbers, I'm sure they'll quickly become evident and be trivially solvable. Still, the code stands as an example of the kind of equivalencies and conversions I was talking about. *thwacks his wrist with a wet noodle, then finally goes to bed* --
|
Sat, 12 Jul 2003 02:40:21 GMT |
|
|
Walter Milne #7 / 12
|
Help: Pointer to 2-D array of structs.
How about this... typedef struct { int a, b, c; } Triple; Triple array2dim[2][2] = { { {0, 1, 2}, {3, 4, 5}, }, { {6, 7, 8 }, {9, 10, 11} } }; int main(void) { Triple (* t)[2]; // so t points to arrays of 2 Triples int i; t = array2dim; // assigns pointer to an array i = t[1][1].a; /* most meaningful */ printf("%d\n", i ); /* outputs 9.. or put it another way.. */ i= (*(t+1))[1].a; /* follow second pointer to array, and get 2nd element */ printf("%d\n",i); /* so does this; .. or the totally awful */ i = (*(*(t+1)+1)).a; /* uurrgghh */ printf("%d\n",i); /* still get 9 */ return 0; }
Quote: > Hello. > I'm having trouble trying wrapping my head around this problem in C: > 1) I have a struct defined > typedef struct { > double a, b, c; > } Triple; > 2) and I use it in a two-dimensional context with multiple instances: > Triple array1[3][2] = { > { {0.5, 0.0, 0.0}, {0.0, 0.0, 0.0} }, > { {0.0, 0.5, 0.0}, {0.0, 0.0, 0.0} }, > { {0.0, 0.0, 0.5}, {0.0, 0.0, 0.0} } > }; > ... > Triple arrayN[3][2] = { > { {1.5, 1.0, 1.0}, {1.0, 1.0, 1.0} }, > { {1.0, 1.5, 1.0}, {1.0, 1.0, 1.0} }, > { {1.0, 1.0, 1.5}, {1.0, 1.0, 1.0} } > }; > 3) Now, later on in the code I would like to create a pointer to point > to one of the arrays depending on a flag: > Triple *p; > if (flag == ARRAY1) { > p = array1; > } ... if (flag == ARRAYN) { > p = arrayN; > } > The Questions are > 1) how do I declare the pointer (is it Triple **p, or Triple *p or ...) > 2) how do I assign the pointer to the reference of the array (is it p = > &array1 or p = &(array1[0] or ...) > 3) how do I access the information with the pinter (is it (*p)[2][1] or > p[2][1] or...) > Thanks for your help. > E.B. > --
--
|
Sat, 12 Jul 2003 02:40:52 GMT |
|
|
Serge #8 / 12
|
Help: Pointer to 2-D array of structs.
Quote: > > As of their being identical. Let's rewrite this: > At no time did I say they were identical, merely that equivalencies existed.
Pardon, you said they were equivalent. My fault, I thought that the equivalence of definitions meant they produced identical objects. Quote: > > As of conversions, the only trivial conversion is from apchar to ppchar. > > The conversion from aachar to ppchar is possible though it would be > > considered suspicious by any decent C compiler. > Err, you mean it's not possible to do > ppchar = (char **)&aachar[0][0]
No, I thought that with trivial conversions you could write ppchar = aachar; and the compiler should swallow this without warnings. Silly thought. Again, it couldn't occure to me that your above statement defines a trivial conversion between ppchar and aachar. Definitely I have to enroll in some C classes. I'm afraid I do not want to read further Sergei --
|
Sun, 13 Jul 2003 07:54:14 GMT |
|
|
David Thompso #9 / 12
|
Help: Pointer to 2-D array of structs.
.... Quote: > Remember that it's 3:00am as I write this, I'm dead tired, and that means > this code might very well be wrong. :) ...
Sure is. Quote: > char *pFoo[4] = > { > "String 1", > "String 2", > "String 3", > NULL > }; > char **ppFoo = pFoo; > /* or, char **ppFoo = &pFoo[0], it's all the same */ > while (ppFoo) > { > printf("%s\n", **ppFoo); > ppFoo++; > }
while( * ppFoo ) printf("%s\n", * ppFoo), ppFoo++; /* or just puts(*ppFoo++); */ Quote: > for (int i = 0 ; i < 3 ; i++) printf("%s\n", *pFoo[i]);
for( /*int*/ i = 0; i < 3; i++ ) puts( ppFoo[i] ); -- - David.Thompson 1 now at worldnet.att.net --
|
Fri, 18 Jul 2003 13:44:46 GMT |
|
|
|