dzoey@terminus.umd.edu (Joe Herman) (03/29/91)
Hello, I have a section of code that scans through a block of variable
length records. The structure looks more or less like this:
struct foo {
unsigned short recsize;
unsigned short num;
char info [24];
byte flags;
char filename[1]
};
Where, foo.filename is a placeholder for a variable length string.
After I process one record, I'd like to just increment the pointer to
point to the next record. What I'd like to do is:
fooptr += fooptr->recsize;
However, the compiler I'm using increments the pointer by
recsize * sizeof (struct foo). This is probably correct.
Next, I tried
fooptr = (char *) fooptr + fooptr->recsize;
No difference, so I guess it gets the value to multiply the increment from
the lvalue.
Is there a way to do what I want without using a temporary variable
(such as assigning to a char * and then doing the increment) or
converting the pointer to an integral type, doing the addition and
converting back?
Thanks,
Joe Herman
dzoey@terminus.umd.edu
--
"Everything is wonderful until you know something about it."
willcr@bud.sos.ivy.isc.com (Will Crowder) (03/30/91)
In article <8334@umd5.umd.edu>, dzoey@terminus.umd.edu (Joe Herman) writes: |> Hello, I have a section of code that scans through a block of variable |> length records. The structure looks more or less like this: |> |> struct foo { |> unsigned short recsize; |> unsigned short num; |> char info [24]; |> byte flags; |> char filename[1] |> }; |> |> Where, foo.filename is a placeholder for a variable length string. |> |> After I process one record, I'd like to just increment the pointer to |> point to the next record. What I'd like to do is: |> |> fooptr += fooptr->recsize; |> |> However, the compiler I'm using increments the pointer by |> recsize * sizeof (struct foo). This is probably correct. Indeed, that is the correct behavior. |> Next, I tried |> |> fooptr = (char *) fooptr + fooptr->recsize; |> |> No difference, so I guess it gets the value to multiply the increment from |> the lvalue. I'm surprised that there was no difference here. The cast of fooptr to (char *) in the expression should have behaved as you expected. Both Sun CC and gcc do what you want here, although both issue a warning about assignments between incompatible pointer types. To quiet the warning and make it clear what you are doing: fooptr = (struct foo *)((char *)fooptr + fooptr->recsize); However, there are other potential pitfalls here having to do with data alignment restrictions. If struct foo needs to be aligned on a particular boundary, then you can get into trouble adding non (sizeof struct foo)-sized chunks to the pointer. (The addition will succeed, or should, but you may get an alignment exception on your next access via fooptr.) |> Thanks, |> Joe Herman |> You're welcome. Hope this helps. OBTW, your compiler may be broken. Which one is it? Will -------------------------------------------------------------------------------- Will Crowder, MTS | "That was setting #1. Anyone want to see (willcr@ivy.isc.com) | setting #2?" INTERACTIVE Systems Corp. | -- Guinan
lamont@uts.amdahl.com (Duane Richard LaMont) (03/30/91)
In article <8334@umd5.umd.edu> dzoey@terminus.umd.edu (Joe Herman) writes: >Next, I tried > >fooptr = (char *) fooptr + fooptr->recsize; > >No difference, so I guess it gets the value to multiply the increment from >the lvalue. You were definitely on the right track, try: (char *) fooptr += fooptr->recsize; Rick LaMont
gwyn@smoke.brl.mil (Doug Gwyn) (03/30/91)
In article <8334@umd5.umd.edu> dzoey@terminus.umd.edu (Joe Herman) writes: >fooptr = (char *) fooptr + fooptr->recsize; This (almost) should have worked. You also need to convert back to the proper pointer type before the assignment: fooptr = (struct foo *) ((char *) fooptr + fooptr->recsize);
id8rld06@serss0.fiu.edu (Michael N Johnston) (03/31/91)
>struct foo { >unsigned short recsize; >unsigned short num; >char info [24]; >byte flags; >char filename[1] >}; >Where, foo.filename is a placeholder for a variable length string. >After I process one record, I'd like to just increment the pointer to >point to the next record. What I'd like to do is: >fooptr += fooptr->recsize; >However, the compiler I'm using increments the pointer by >recsize * sizeof (struct foo). This is probably correct. If you are declaring foo_ptr as struct foo *foo_ptr; then this is indeed correct operation. What you need to do to incrment foo_ptr to point to the next record is (assuming foo_ptr is pointing to an array of struct foo): ++foo_ptr; If you plan to store a char array in filename DON'T. Use char *filename and point this to your actual array. Using your origional declaration and doing something like strcpy(foo_ptr->filename, "abcde") will lead to disaster. Good Luck, Mike -- ==================================================================== Michael Johnston id8rld06@serss0.fiu.edu or
berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) (04/11/91)
In article <15631@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >In article <8334@umd5.umd.edu> dzoey@terminus.umd.edu (Joe Herman) writes: >>fooptr = (char *) fooptr + fooptr->recsize; >This (almost) should have worked. You also need to convert back to >the proper pointer type before the assignment: > fooptr = (struct foo *) ((char *) fooptr + fooptr->recsize); No, not needed, the cast is implicit. -- Sincerely, berg@marvin.e17.physik.tu-muenchen.de Stephen R. van den Berg. "I code it in 5 min, optimize it in 90 min, because it's so well optimized: it runs in only 5 min. Actually, most of the time I optimize programs."
berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) (04/11/91)
Duane Richard LaMont writes: >You were definitely on the right track, try: > (char *) fooptr += fooptr->recsize; THAT, is not allowed. (See discussion about "increment casted void-pointer"). -- Sincerely, berg@marvin.e17.physik.tu-muenchen.de Stephen R. van den Berg. "I code it in 5 min, optimize it in 90 min, because it's so well optimized: it runs in only 5 min. Actually, most of the time I optimize programs."
willcr@bud.sos.ivy.isc.com (Will Crowder) (04/12/91)
In article <4205@rwthinf.UUCP>, berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) writes: |> In article <15631@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: |> >In article <8334@umd5.umd.edu> dzoey@terminus.umd.edu (Joe Herman) writes: |> >>fooptr = (char *) fooptr + fooptr->recsize; |> |> >This (almost) should have worked. You also need to convert back to |> >the proper pointer type before the assignment: |> |> > fooptr = (struct foo *) ((char *) fooptr + fooptr->recsize); |> |> No, not needed, the cast is implicit. But will result in a compiler warning on most compilers. It also makes it quite clear what is going on. You cannot blithely assign one pointer type to another without expecting some kind of complaint from the compiler. |> -- |> Stephen R. van den Berg. -------------------------------------------------------------------------------- Will Crowder, MTS | "I was gratified to be able to answer promptly, (willcr@ivy.isc.com) | and I did: I said I didn't know." INTERACTIVE Systems Corp. | -- Mark Twain
gwyn@smoke.brl.mil (Doug Gwyn) (04/13/91)
In article <4205@rwthinf.UUCP> berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg) writes: >No, not needed, the cast is implicit. No, without the cast you have violated a constraint in the C standard (section 3.3.16.1 in ANS X3.159-1989) and a standard-conforming implementation is obliged to produce a diagnostic.