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

Re: C programming question



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.  The
>>  volume_label structure is apparently a based structure, as references to
>>  the volkey variable look something like this:
> 
> 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));
> }
> 
> Hope that helps.

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.  They will
overlap each other implicitly because their pointers are the same.  Both
structure mappings occupy exactly 80 bytes of storage.  And the storage for
one of them is already allocated somehow.  What I need to do
is associate a pointer with the new structure and assign a value to the pointer that
matches the pointer for the other structure.  That will implicitly cause the
two structures to overlap in storage.  Here are examples from two
other languages that I do know: s390 assembler language and PL/I.
Here is the assembler example:

----------

         ...
         CLC   LABELIDA,=C'VOL1'            Is this structure type A?
         BE    VOL1CODE                     Yes - branch to label VOL1CODE
         LA    3,STRUCTA                    No - load the address of STRUCTA into register 3
         USING STRUCTB,3                    Tell the assembler that the address of STRUCTB is in register 3
         L     4,FIELDB2                    Load the fullword at FIELDB2 into register 4
         ...                                Perform additional processing
         DROP  3                            Tell the assembler that it can no longer assume that register 3 points to STRUCTB
         B     COMCODE                      Rejoin common code
VOL1CODE DS    0H  
         ...                                Proceed with processing for structure type A
COMCODE  DS    0H
         ...
STRUCTA  DS    0CL12
LABELIDA DS    CL4
FIELDA1  DS    CL8
         ...
STRUCTB  DSECT ,                            Start a dummy control section (based structure)
LABELIDB DS    CL4
FIELDB1  DS    F
FIELDB2  DS    F
         ...

----------

Here is the PL/I example:

----------

   DCL 1 STRUCTA,
         2 LABELIDA CHAR (4),
         2 FIELDA1 CHAR (8);

   DCL ADDR BUILTIN;
   DCL B_PTR POINTER;

   DCL 1 STRUCTB BASED (B_PTR),
         2 LABELIDB CHAR (4),
         2 FIELDB1 FIXED BINARY (31,0),
         2 FIELDB2 FIXED BINARY (31,0);
   ...
   IF LABELIDA = 'VOL1' THEN
      DO;
         /* Processing that refers to elements of STRUCTA */
      END;
   ELSE
      DO;
         B_PTR = ADDR(STRUCTA);
         /* Processing that refers to elements of STRUCTB */
      END;

----------

Now back to C.
At the point in the code where I need to make a reference to the "disk_offset"
member of the "cms_label" structure, I know that I can validly reference the
"volkey" variable of the "volume_label" structure like this:

   disk_specific->anchor->vlabel->volkey

What I need to do is declare that "cms_label" is a based structure and
associate a pointer variable, say "cms_ptr", with it.  But I don't want
any storage to be allocated for the structure: only for the pointer.
Storage should be allocated for the pointer, but it should not be initialized
to anything.  Then I can assign a value to the pointer, with something like:

   cms_ptr = disk_specific->anchor->vlabel;

Then I can make references to members of the cms_label structure implicitly
using the cms_ptr pointer variable.  No storage is ever allocated to the
"cms_label" structure.  It overlays the "volume_label" structure implicitly
via the assignment of a value to its associated pointer variable.  I know
how to do something like this in s390 assembler language and PL/I.  Surely
there must be a way to do this in C, right?

In short, I need to (a) declare "cms_label" as a based structure, (b)
declare a pointer variable called  "cms_ptr" and associate it with the
"cms_label" structure, (c) make sure that the compiler does not attempt
to allocate any storage for the "cms_label" structure, (d) make sure that
the compiler automatically acquires storage for the "cms_ptr" pointer
variable itself, (e) assign the address of the "volume_label" structure
to the "cms_ptr" pointer variable at an appropriate point in the code,
and (f) make references to the members of the cms_label structure.
How do I do this?  (Man, I wish I knew C!)

-- 
  .''`.     Stephen Powell    
 : :'  :
 `. `'`
   `-


Reply to: