Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!elroy.jpl.nasa.gov!decwrl!world!ksr!jfw From: jfw@ksr.com (John F. Woods) Newsgroups: comp.std.c Subject: Re: so how do I do it? (was Re: call to revolt) Message-ID: <4269@ksr.com> Date: 28 Jun 91 15:23:31 GMT References: Sender: news@ksr.com Lines: 84 minar@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:"