jcrowe@shaffer.UUCP (Joe Crowe) (02/10/89)
Consider this a niave question. I have a structure which contains among
other things a pointer to an array of structures declared as follows:
typedef struct XYZ
{
.
.
.
struct diag_cmd (*p_cmd_blk)[];
.
.
} t_xyz;
I am allocating storage for the above structures dynamically and
setting the pointer p_cmd_blk manually. All of this works. But when
I try various methods of accessing a structure member one of the array
of structures I am getting compiler errors. I have tried most combinations
but with no luck. Any ideas??
Thanks in advance.
Joseph Crowe
scjones@sdrc.UUCP (Larry Jones) (02/11/89)
In article <1707@shaffer.UUCP>, jcrowe@shaffer.UUCP (Joe Crowe) writes: > Consider this a niave question. I have a structure which contains among > other things a pointer to an array of structures declared as follows: > > typedef struct XYZ > { > . > . > . > struct diag_cmd (*p_cmd_blk)[]; > . > . > } t_xyz; > > I am allocating storage for the above structures dynamically and > setting the pointer p_cmd_blk manually. All of this works. But when > I try various methods of accessing a structure member one of the array > of structures I am getting compiler errors. I have tried most combinations > but with no luck. Any ideas?? The rule of thumb is C is declarations look just like references and vice versa. (Of course, you do have to correct for the structure name being in a different place in the declaration than in the usage.) Just work it out one level at a time. The references would look like: xyz_struct - struct XYZ xyz_struct.p_cmd_blk - ptr to ary of structs (*xyz_struct.p_cmd_blk) - ary of structs (*xyz_struct.p_cmd_blk)[i] - struct diag_cmd (*xyz_struct.p_cmd_blk)[i].member - member ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC scjones@sdrc.UU.NET 2000 Eastman Dr. BIX: ltl Milford, OH 45150 AT&T: (513) 576-2070 "When all else fails, read the directions."
scs@adam.pika.mit.edu (Steve Summit) (02/13/89)
In article <1707@shaffer.UUCP> jcrowe@shaffer.UUCP (Joe Crowe) writes: >I have a structure which contains among >other things a pointer to an array of structures declared as follows: >typedef struct XYZ >{ > struct diag_cmd (*p_cmd_blk)[]; >} t_xyz; > > I am allocating storage for the above structures dynamically and >setting the pointer p_cmd_blk manually. All of this works. While your declaration of a pointer to an array of structures is correct, it has two problems: 1. The array size isn't specified, making this pointer even less useful than most pointers to arrays. 2. It probably isn't what you want. I suspect that the intent was that an XYZ structure contain an arbitrary number of diag_cmd structures, with the number unknown at compile time. That is, you wanted something like struct diag_cmd p_cmd_blk[n]; where n is determined at run time (n is probably another member of the XYZ structure). What you want is struct diag_cmd *p_cmd_blk; which can be initialized with t_xyz.p_cmd_blk = (struct diag_cmd *)malloc(n * sizeof(struct diag_cmd)); and dereferenced with t_xyz.p_cmd_blk[i].cmd_blk_field The key is that a pointer to a structure (or any kind of pointer, for that matter) need not point to only one instance of the structure. In this case, it "points at" an "array" of n structures, although the pointer's type is "pointer to structure" rather than "pointer to array of structure." For the usual cases, "pointer to struct" is in fact preferable; pointer arithmetic (and, by extension, array-like subscripting) works as you probably want it to: selecting among the various single structures in the "array" of n of them. (In this paragraph, I have used the terms "points at" and "array", in quotes, in a loose way -- struct diag_cmd *p_cmd_blk neither declares an array, nor, formally, points at one, but once allocated, it acts like an array for all practical purposes.) "pointer to array of struct" would, on the other hand, increment or index over entire arrays of structures at once, which is why it's a fairly useless concept if the size of the array is unspecified. (Many compilers get pointers to arrays wrong, which is both unsurprising, since they're so confusing, and benign, since they're so rarely useful. I suspect that "pointer to array" with the size of the array unspecified should elicit a warning or error message. pcc apparently pretends that the size is zero, because incrementing the pointer adds 0 to it. My C interpreter says "missing array dimension.") Although true pointers to arrays could be made to work in this example, they would require extradereferencing and punctuation, and generally only confuse the issue. Steve Summit scs@adam.pika.mit.edu P.S. This example helps to illustrate why, if something of type "array of X" appears in a C expression, it is converted into a pointer with type "pointer to X" (rather than "pointer to array of X"). The resultant pointer "acts like" the original array; i.e. after saying p=a, p[i] references a[i].
throopw@xyzzy.UUCP (Wayne A. Throop) (02/13/89)
> jcrowe@shaffer.UUCP (Joe Crowe) > I have a structure which contains among > other things a pointer to an array of structures declared as follows: > typedef struct XYZ > { ... > struct diag_cmd (*p_cmd_blk)[]; > ... } t_xyz; > I try various methods of accessing a structure member one of the array > of structures I am getting compiler errors. I have tried most combinations > but with no luck. Any ideas?? Um.... maybe I'm being naive myself, but did you try the obvious one, the one you declared it with? That is, (*t_xyz.p_cmd_blk)[N] "It works for me." In particular, I did this: $ cc -g -o t46 t46.c $ mxdb t46 Scanning executable file... (debug) view 1 #include <malloc.h> 2 struct diag_cmd { int i }; 3 struct { struct diag_cmd (*p_cmd_blk)[]; } t_xyz; 4 main(){ * 5 t_xyz.p_cmd_blk = (struct diag_cmd (*)[])malloc(4); 6 (*t_xyz.p_cmd_blk)[0].i = 23; 7 } (debug) breakpoint 7;continue Stopped at frame 1: line 7 of \t46\main, PC main+024 breakpoint "0" taken (debug) evaluate (*t_xyz.p_cmd_blk)[0].i 23 (debug) describe t_xyz struct { struct { int i; } (*p_cmd_blk)[]; } t_xyz; (debug) bye -- The seeds of crime bear bitter fruit. --- Dick Tracy -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (02/14/89)
In article <3374@xyzzy.UUCP>, throopw@xyzzy.UUCP (Wayne A. Throop) writes: | > jcrowe@shaffer.UUCP (Joe Crowe) | > I have a structure which contains among | > other things a pointer to an array of structures declared as follows: | > typedef struct XYZ | > { ... | > struct diag_cmd (*p_cmd_blk)[]; | > ... } t_xyz; | > I try various methods of accessing a structure member one of the array | > of structures I am getting compiler errors. I have tried most combinations | > but with no luck. Any ideas?? | | Um.... maybe I'm being naive myself, but did you try the obvious one, | the one you declared it with? That is, | | (*t_xyz.p_cmd_blk)[N] Um...isn't (*p_cmd_blk)[] an array of pointers, not a pointer to an array? try *(p_cmd_blk[]). K&R (old) Page 110 says that int *b[10] is an array of 10 pointers to int; therefore, struct diag_cmd *p_cmd_blk[] should be an array of pointers to struct diag_cmd. Somehow I doubt that the parens around *p_cmd_blk are grouping things differently. Ayway, there's always struct diag_cmd **p_cmnd_blk. -- Name: Christopher J. Calabrese Brain loaned to: AT&T Bell Laboratories, Murray Hill, NJ att!ulysses!cjc cjc@ulysses.att.com Obligatory Quote: ``Now, where DID I put that bagel?''
cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (02/14/89)
In article <11216@ulysses.homer.nj.att.com>, I write > Um...isn't (*p_cmd_blk)[] an array of pointers, not a pointer to an array? > try *(p_cmd_blk[]). These things always confuse me to no end. Advanced C Tips and Techniques (page 218) says (*foo)[] should be a pointer to an array. I still think a pointer to a pointer is the best way. -- Name: Christopher J. Calabrese Brain loaned to: AT&T Bell Laboratories, Murray Hill, NJ att!ulysses!cjc cjc@ulysses.att.com Obligatory Quote: ``Now, where DID I put that bagel?''
sarima@gryphon.COM (Stan Friesen) (02/14/89)
In article <1707@shaffer.UUCP> jcrowe@shaffer.UUCP (Joe Crowe) writes: > >typedef struct XYZ >{ > . > . > . > struct diag_cmd (*p_cmd_blk)[]; > . > . >} t_xyz; > > I am allocating storage for the above structures dynamically and >setting the pointer p_cmd_blk manually. All of this works. But when >I try various methods of accessing a structure member one of the array >of structures I am getting compiler errors. I have tried most combinations >but with no luck. Any ideas?? > Even though I have seen one article with the correct solution, (you probably meant 'struct diag_cmd *p_cmd_blk'), I will put in my two cents worth. This confusion between pointers to the first element of an array and pointers to arrays is very common. I would recommend that Mr Koenig's "C Traps and Pitfalls" become standard reading for everyone learning 'C'. It has an excellent chapter on just this issue, and is probably worth the price just for that chapter alone. -- Sarima Cardolandion sarima@gryphon.CTS.COM aka Stanley Friesen rutgers!marque!gryphon!sarima Sherman Oaks, CA
chris@mimsy.UUCP (Chris Torek) (02/14/89)
In article <11217@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes: >These things always confuse me to no end. ... Indeed. >I still think a pointer to a pointer is the best way. No. Steve Summit posted the correct answer (including the fact that, other than in a very few special cases, C arrays MUST have a size). Read his article. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
rbutterworth@watmath.waterloo.edu (Ray Butterworth) (02/15/89)
In article <11217@ulysses.homer.nj.att.com>, cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes: > In article <11216@ulysses.homer.nj.att.com>, I write > > Um...isn't (*p_cmd_blk)[] an array of pointers, not a pointer to an array? > > try *(p_cmd_blk[]). > > These things always confuse me to no end. > Advanced C Tips and Techniques (page 218) says (*foo)[] should be a pointer > to an array. I still think a pointer to a pointer is the best way. They are only confusing if one tries to think about it. The trick is don't think. i.e. read it exactly as it says it is, and in the occasional case where the type you end up with really is array, and if array is not meaningful in the context, then and only then change array to pointer to element of array. e.g. (*foo)[3] explicitly says foo is a pointer to an array of 3 elements, so, if you use sizeof(*foo), then you should get the size of the array, since that is exactly what you asked for, but if you use func(*foo), then since it is not possible to pass arrays to functions you get a pointer to the first element of *foo. Similarly if you have "x = *foo;", then *foo is an array, but since you cannot assign arrays (i.e. have them on the right of an =, i.e. have them as r-values), the compiler silently turns the reference to the array to a pointer to its first element. Another handy style guideline to follow is trying to avoid writing empty [] declarations. If the [] is empty, then you are talking about an array of unknown size and in the event that you really do want the array there is no way that the compiler will know how big it is. If you don't know how big an array is, then perhaps you shouldn't be talking about arrays but about pointers. In particular never declare a function parameter as an array. e.g. use "char **argv;", not "char *argv[];". Since the compiler will silently convert the second parameter declaration into the first for you, you might as well declare it that way in the first place and avoid confusing yourself and others.