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.