[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: C programming question



On Thursday 15 April 2010 13:56:00 Stephen Powell wrote:
> On Wed, 14 Apr 2010 23:10:55 -0400 (EDT), Boyd Stephen Smith Jr. wrote:
> > On Tuesday 13 April 2010 17:16:03 Stephen Powell wrote:
> >> What I need to do is to have two structures overlay each other; so that
> >>  they occupy the same storage.  To be specific, here is a structure
> >> which describes the volume label for an OS-formatted disk:
> >>
> >> struct __attribute__ ((packed)) volume_label {
> >>         char volkey[4];         /* volume key = volume label */
> >> ...
> >> };
> >>
> >> And here is a structure which describes the volume label for a
> >>  CMS-formatted disk:
> >>
> >> struct __attribute__ ((packed)) cms_label {
> >>         char label_id[4];       /* Label identifier */
> >> ...
> >> };
> >
> > union any_label {
> > 	struct volume_label vl;
> > 	struct cms_label    cl;
> > };
> >
> >> Note that both structures have as their first member a character
> >> variable of length 4.  In the case of the "volume_label" structure it is
> >> "volkey" and in the case of the "cms_label" structure it is "label_id". 
> >> If the value of this variable is "VOL1" (in EBCDIC) then it is the first
> >> structure which maps the storage.  If the value of this variable is
> >> "CMS1" (in EBCDIC) then it is the second structure which maps the
> >> storage.
> >
> > union any_label *label = /* Initialize somehow */;
> > struct volume_label *maybe_vl = &label->vl;
> > struct cms_label *maybe_cl = &label->cl;
> >
> > if (strncmp(maybe_vl->volkey, "VOL1", 4) == 0) {
> >     maybe_cl = NULL;
> >     /* Use maybe_vl all you want, e.g. */
> >     maybe_vl->security = 0xFF;
> > } else if (strncmp(maybe_cl->label_id, "CMS1", 4) == 0) {
> >     maybe_vl = NULL;
> >     /* Use maybe_cl all you want, e.g. */
> >     printf("%lu\n", (unsigned long) maybe_cl->disk_offset);
> > } else {
> >     assert(("Unrecognized disk!", 0));
> > }
> 
> Thanks, Boyd.  Your response comes the closest so far to what I'm looking
> for.  Based on what I know from other programming languages, I don't think
> it's going to be necessary to explicitly declare a union.

It's possible, but I would generally do it for clarity.  I like using the 
types of variables/arguments as documentation, so I would store any data where 
the real type was unknown in the union.  Then access it though a "struct 
cms_label *" or "struct volume_label *" one I had determined the correct type.

Since C unions are not tagged, a C union is the same size as it's largest 
member.  (NB: Not really sure how __attribute__((__packed__)) changes things, 
if at all; it's possible you need it on the union to prevent padding from 
being added after the space occupied by the largest member.)

> In short, I need to (a) declare "cms_label" as a based structure,

(above; timmmed)

> (b)
> declare a pointer variable called  "cms_ptr" and associate it with the
> "cms_label" structure,

struct cms_label *cms_ptr;

Initialization optional, but recommended.

> (c) make sure that the compiler does not attempt
> to allocate any storage for the "cms_label" structure,

Since you are declaring a pointer to a structure, and not declaring an object 
with type "struct cms_label", no space will be allocated for a cms_label.

> (d) make sure that
> the compiler automatically acquires storage for the "cms_ptr" pointer
> variable itself,

Make your declaration a definition and that'll be handled.  (Declarations and 
definitions look very similar for non-function types; the code given above is 
actually a definition if it is not within a struct/union type.)

> (e) assign the address of the "volume_label" structure
> to the "cms_ptr" pointer variable at an appropriate point in the code,
> and

struct volume_label vl;
struct cms_label *cms_ptr;

/* Load data into vl */
/* Determine that the data is actually a cms_label */
cms_ptr = (void *) &vl;

Or, in your specific case, you should be able to do something like:

struct cms_label *cms_ptr = (void *) disk_specific->anchor->vlabel;

Since you are already dealing with a "struct volume_label *", there's no need 
for the address-of operator (&).

> (f) make references to the members of the cms_label structure.

cms_ptr->label_id; /* Or any other member. */

> How do I do this?  (Man, I wish I knew C!)

Examples above good?  Please let me know if I can provide further assistance.
-- 
Boyd Stephen Smith Jr.           	 ,= ,-_-. =.
bss@iguanasuicide.net            	((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy 	 `-'(. .)`-'
http://iguanasuicide.net/        	     \_/

Attachment: signature.asc
Description: This is a digitally signed message part.


Reply to: