so how do I do it? (was Re: call to revolt)

John F. Woods jfw at ksr.com
Sat Jun 29 01:23:31 AEST 1991


minar at reed.edu writes:
>If
>void * p;
>(int *)p++;
>is illegal, how do I do what I mean?

Since it is illegal, you'll have to explain what you WANT it to main.

>I'm writing some code right now that needs to extract information from a
>buffer that contains various types in it. Lets say that there's a chunk of
>memory that I *know* first contains a char, then an unsigned. I want to get
>these values.

Ah.

>The obvious way to do it is
>struct foo {
>  char c;
>  unsigned u;
>};
>and then (struct foo *)p->c  or (struct foo *)p->u
>this is nonportable, as to my understanding, as struct arrangements are not
>guaranteed.

They are guaranteed.  The address of p->c is guaranteed to be less than the
address of p->u.  Of course, the PADDING is implementation defined.


>The next best thing is:
>*(char *)p
>to get the char.

Yes.

>Then, I want to get to the unsigned that's next, so the obvious next step is
>(char *)p++

Not it you plan to program in C.

p = (char *)p + sizeof(char);

will increment p by the size of a char.  NOTE:  I assume you think you can then
type

*(unsigned *)p

to get the value of the unsigned int which follows, and this is WRONG.  A wide
variety of interesting (i.e. neither VAX nor washing-machine-controller)
machines will take addressing exceptions if you access objects on random
alignments.  To access that unsigned int will require something like

unsigned int victim;
bcopy(p, &victim, sizeof(unsigned int));	/* or your favorite memory
						 * mover or even a carefully
						 * chosen macro
						 */
p = (char *)p + sizeof(unsigned int);

But this, of course, assumes that the byte-order in that packed "structure"
is the same as the machine's natural byte-order; if you're exchanging these
"structures" with another machine (via disk file or network) that may not
be the case, in which case "accessor macros" are an excellent idea here (i.e.
the putlong()/getlong() macros found in the BSD named resolver routines).

This kind of problem has been solved correctly and well in C over and over
again.

>I don't have to write this code portably, but I'd like to write it correctly
>according to ANSI anyway.

Note that unportable code is not only a problem when you finally upgrade from
your 8080 system to a Laptop Cray; it can cause you grief the next time you
get a compiler upgrade (hahahahahahahahahahahaha) or even using the same
compiler, if it is an aggresive optimizer which prizes speed of code over
consistency in undefined cases.

>while I'm at it, how do you get the offset of an element of a structure
>the ANSI way?

Using the offsetof() macro.  Please go buy and read an ANSI C manual.

"I'm having troubles with an Ada program; I don't actually have an Ada manual,
nor have I ever seen one, so I just typed in the following BASIC program, and
I don't understand why it doesn't work:"



More information about the Comp.std.c mailing list