Re: advantage of using typedefs



>> "Rod Pemberton" <dont_have@xxxxxxxxxxxxx> writes:
>>>When structures are typedef'd, you can cast values to
>>>structure elements and take the size of structure elements
>>>without actually having a valid, allocated, and filled data
>>>structure. ...

(This is not quite right as stated, but I think I know what you
mean. However, there is nothing about "typedef" that makes any
difference here.)

>"Keith Thompson" <kst-u@xxxxxxx> wrote in message
>news:lnirs2sh0v.fsf@xxxxxxxxxxxxxxxxxx
>> Given:
>>
>> typedef struct foo_s {
>> /* member declarations */
>> } foo_t;
>>
>> I can't think of anything you can do with "foo_t" that you can't just
>> as easily do with "struct foo_s" ...

In article <ksc0b3-bp52.ln1@xxxxxxxxxxxxxxxxx>
Rod Pemberton <dont_have@xxxxxxxxxxxxx> wrote:
>It could be used anywhere nested structures are used, such as a database.
>But, let's work with two hard disk structures: 'partition boot sector' and
>'bios parameter block' (which is part of the 'partition boot sector'). Say
>you have a buffer, 'buf[512]', of unsigned char for reading sectors off the
>hard disk. Now, you've read the partition boot sector off the hard disk
>into your buffer. How do you get access data in the 'bios parameter block'
>by name instead of by 'buf[x]'? You cast the buffer to a 'partition boot
>sector'. From the 'partition boot sector', you get the offset of the 'bios
>parameter block' which is then cast to a 'bios parameter block'. From the
>casted 'bios parameter block', you get the data you need. For example, to
>get the number of heads (FAT32X) (this is from working code) :
>
>unsigned char buf[512];
>//some disk read routine which gets the partition boot sector, not the
>master boot sector
>num_heads=((bios_parameter_block *)&(((partition_boot_sector
>*)&buf)->bpb))->number_of_heads;

Given:

struct bios_parameter_block { ... };
struct partition_boot_sector { ... };

(and no typedefs) I can rewrite what you have written as:

num_heads =
((struct bios_parameter_block *)
&(((struct partition_boot_sector *)&buf)->bpb))->number_of_heads;

though I would not write it like this, for a number of reasons.

Note that "&buf" is not needed here, because "buf" has type "array
512 of unsigned char", so that the "value" of buf falls under The
Rule and becomes a pointer to the first element of "buf". The
difference between &buf[0] and &buf is the type of the resulting
pointer.

If alignment and byte order are not concerns (i.e., if this code
is not intended to be portable), I would probably write:

struct partition_boot_sector *pbs;
struct bios_parameter_block *bpb;
...
pbs = (struct partition_boot_sector *)buf;
bpb = &pbs->bpb; /* (presumably this already has the right type) */
num_heads = bpb->number_of_heads;

If pbs->bpb does not have the correct type for some reason, the
second assignment would also need a cast.

>As long as the layout of the structures are correct (i.e., packed, if
>necessary) ...

Structure packing is of course not portable, so we should not even
mention it on comp.lang.c :-)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
.