geoff@burl.UUCP (geoff) (04/25/85)
Greetings, I am trying to allocate a dynamic two-dimensional array of structures. I don't get any complaints from the compiler about this test program, but it doesn't work correctly, either. I would expect the array 'l' and the pointer 'p' to store the data in the same places (relative to the beginning of storage, that is). However, while 'l' correctly packs the data into 8 contiguous words, 'p' loads the data into every other 2-word segment. If I increase the column dimension of p to 3, it loads it into every third 2-word segment. It obviously considers each element to be the full column size, but only uses the first structure in that element. The assembly language is of no help -- it shows the data loaded into constant offsets from the address of j (as it should -- the offsets are just wrong). I am including the program and its output. What am I doing wrong?? How do I do it right?? many thanks-- geoff sherwood int j[100]; /* just getting some initialized space */ main() { struct fred { int i; int j; }; struct fred (*p)[2][2]; struct fred (l)[2][2]; int i, *ip; p = (struct fred (*)[2][2])j; /* I was rather suprised to have to use -> rather than . /* does make some sense -- p is a pointer -- but if c is * a character pointer, c[0] is the zero-eth element, not * a pointer to it. */ p[0][0]->i = 9; p[0][0]->j = 10; p[0][1]->i = 99; p[0][1]->j = 100; p[1][0]->i = 999; p[1][0]->j = 1000; p[1][1]->i = 9999; p[1][1]->j = 10000; l[0][0].i = 9; l[0][0].j = 10; l[0][1].i = 99; l[0][1].j = 100; l[1][0].i = 999; l[1][0].j = 1000; l[1][1].i = 9999; l[1][1].j = 10000; for (i = 0; i < 16; i++ ) printf("j[%d] = %d\n", i, j[i]); ip = (int *)l; for (i=0, ip = (int *)l; i < 8; i++) printf("ip[%d] = %d\n", i, ip[i]); } (output of said test) j[0] = 9 j[1] = 10 j[2] = 0 j[3] = 0 j[4] = 99 j[5] = 100 j[6] = 0 j[7] = 0 j[8] = 999 j[9] = 1000 j[10] = 0 j[11] = 0 j[12] = 9999 j[13] = 10000 j[14] = 0 j[15] = 0 ip[0] = 9 ip[1] = 10 ip[2] = 99 ip[3] = 100 ip[4] = 999 ip[5] = 1000 ip[6] = 9999 ip[7] = 10000
alexis@reed.UUCP (Alexis Dimitriadis) (04/29/85)
In article <669@burl.UUCP> geoff@burl.UUCP (geoff) writes: > ... while 'l' correctly packs the data into 8 >contiguous words, 'p' loads the data into every other 2-word segment. If >I increase the column dimension of p to 3, it loads it into every third >2-word segment. >What am I doing wrong?? How do I do it right?? > >int j[100]; /* just getting some initialized space */ >main() >{ > struct fred { > int i; > int j; > }; > struct fred (*p)[2][2]; > struct fred (l)[2][2]; > int i, *ip; > > p = (struct fred (*)[2][2])j; That's easy! The way you declare p, it is a pointer to a two-by-two array of fred. Since p[n] is equivalent to *(p+n), the first index increments by the size of the pointed object--In fact you could use p[x][y][z] without getting a diagnostic from the compiler. The correct way to do this would be to declare struct fred l[2][2], *p[2]; Then you could use p[n], to access the n-1st 8 byte block of memory starting at *p, as in p[n][1].i (and not p[n][1]->i !) Alexis Dimitriadis -- _______________________________________________ As soon as I get a regular job, the opinions expressed above will attach themselves to my employer, who will never be rid of them again. alexis @ reed ...ihnp4!{harvard|tektronix}!reed ...decvax!tektronix!reed ...teneron!reed
donn@utah-gr.UUCP (Donn Seeley) (04/30/85)
From: geoff@burl.UUCP (geoff) I am trying to allocate a dynamic two-dimensional array of structures. ... (Did you figure this out? I noticed some cancel messages lying around that looked like they might have been intended to nab your article... In the event you were serious about posting this, and in consideration that this might conceivably be of general interest, I'll answer your question anyway...) The problem is that you aren't dereferencing your pointer properly. The pointer is declared correctly: struct fred (*p)[2][2]; But for some reason you didn't use it the way it was declared: p[1][1]->j = 10000; We can rewrite this in a trivial way so that we can see what's wrong: p[1][1][0].j = 10000; What this actually does is select the NEXT two-dimensional array after the one to which 'p' points, extract element <1,0> from it and assign 10000 to its member, 'j'. The rule of thumb that was overlooked here is that the declaration of a C object parallels its use; thus the proper way to write what you want is: (*p)[1][1].j = 10000; Hope this helps, Donn Seeley University of Utah CS Dept donn@utah-cs.arpa 40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn