Help: Pointer to 2-D array of structs.
Author Message
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...)

E.B.
--

Thu, 10 Jul 2003 13:22:57 GMT
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
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
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
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
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

*thwacks his wrist with a wet noodle, then finally goes to bed*
--

Sat, 12 Jul 2003 02:40:21 GMT
Help: Pointer to 2-D array of structs.

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...)

> E.B.
> --

--

Sat, 12 Jul 2003 02:40:52 GMT
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
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

 Page 1 of 1 [ 12 post ]

Relevant Pages