Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

advantage of using typedefs

5 views
Skip to first unread message

junky_...@yahoo.co.in

unread,
Jan 28, 2006, 2:55:30 AM1/28/06
to
I was looking at the source code of linux or open BSD. What I found
that lots of typedefs
were used. For example, consider the offset in a file. It was declared
as
off_t offset;
and off_t is typedefed as
typedef long off_t;

I wanted to know what advantage do we get by typedefs ? Why we did not
declare
offset simply as
long off_t;

Similar is the case with size of file and so on.....

Does any one has any clue of why do we use typedefs in such cases ?

Thanx for any help advance ....

Emmanuel Delahaye

unread,
Jan 28, 2006, 3:14:33 AM1/28/06
to
junky_...@yahoo.co.in a écrit :

> I wanted to know what advantage do we get by typedefs ? Why we did not
> declare
> offset simply as
> long off_t;

It's often a portability issue. Imagine you want a type that hold the
biggest possible unsigned integer.

You will have this in C90:

typedef unsigned long biggest_int_t;

and that on C99:

typedef unsigned long long biggest_int_t;

With the help of some smart macros and #ifxxx directives, After a simple
recompile, the type will automagically be corrected after a simple
recompile of the project/lib or whatever.

--
A+

Emmanuel Delahaye

junky_...@yahoo.co.in

unread,
Jan 28, 2006, 3:50:55 AM1/28/06
to

Thanx for your reply, Emmanuel. But if this is the case (ie we need
the biggest possible
unsigned integer to hold offset ) then why not declare
unsigned long long offset;
I believe unsigned long long should be highest possible integer type ?
Or am I wrong ?

Is there any other reason for doing that ?

Mark McIntyre

unread,
Jan 28, 2006, 7:05:30 AM1/28/06
to
On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
"junky_...@yahoo.co.in" <junky_...@yahoo.co.in> wrote:

(concerning typdef'ing)

>Thanx for your reply, Emmanuel. But if this is the case (ie we need
>the biggest possible unsigned integer to hold offset ) then why not declare
>unsigned long long offset;

Because then its size would vary from platform to platform, and on a
c90 implementation it would be an error. Some implementations spell
"long long" as "__int64", others don't support it at all etc etc.

>I believe unsigned long long should be highest possible integer type ?
>Or am I wrong ?

You're right, but the size of long long varies from platform to
platform
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

Thad Smith

unread,
Jan 28, 2006, 12:50:32 PM1/28/06
to
junky_...@yahoo.co.in wrote:
> Emmanuel Delahaye wrote:
>
>>junky_...@yahoo.co.in a écrit :
>>
>>>I wanted to know what advantage do we get by typedefs ? Why we did not
>>>declare
>>>offset simply as
>>>long off_t;
>>
>>It's often a portability issue. Imagine you want a type that hold the
>>biggest possible unsigned integer.

That is one good reason. I often define types for another: I create my
own conceptual data type, which I document where the typedef occurs.
For example:

typedef unsigned long ticks; /* elapsed time, unit = 16 us. */
...
ticks pulseWidth; /* width of last pulse */
ticks pulseInterval; /* time between last 2 pulses */
void DelayTicks (ticks delay);

Here using ticks carries with it the type of data and the scaling.

--
Thad

William J. Leary Jr.

unread,
Jan 28, 2006, 11:40:08 AM1/28/06
to
"Thad Smith" <Thad...@acm.org> wrote in message
news:43db9067$0$81213$892e...@auth.newsreader.octanews.com...

> junky_...@yahoo.co.in wrote:
> >>It's often a portability issue. Imagine you want a type that hold the
> >>biggest possible unsigned integer.
>
> That is one good reason. I often define types for another: I create my
> own conceptual data type, which I document where the typedef occurs.
> For example:
>
> typedef unsigned long ticks; /* elapsed time, unit = 16 us. */
> ...
> ticks pulseWidth; /* width of last pulse */
> ticks pulseInterval; /* time between last 2 pulses */
> void DelayTicks (ticks delay);
>
> Here using ticks carries with it the type of data and the scaling.

From a tools perspective, this can be quite powerful. I've picked up
development on a project where the former developer used typedefs just as
you've done above. One of the advantages is that when I encounter one of his
typedef'd items, I can do a right-click on it and one of the menu options is
"show typedef" which, when selected, shows the typedef, in context. Thus, I
can immediately tell what he meant the variable or argument to hold or
represent. Very handy, and saves a pile of time. Even in the older system
where I have to find them using grep, it still means that once I've found it,
the comments on what it means are right there.

- Bill


Keith Thompson

unread,
Jan 28, 2006, 2:32:56 PM1/28/06
to
Mark McIntyre <markmc...@spamcop.net> writes:
> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
> "junky_...@yahoo.co.in" <junky_...@yahoo.co.in> wrote:
>
> (concerning typdef'ing)
>
>>Thanx for your reply, Emmanuel. But if this is the case (ie we need
>>the biggest possible unsigned integer to hold offset ) then why not declare
>>unsigned long long offset;
>
> Because then its size would vary from platform to platform, and on a
> c90 implementation it would be an error. Some implementations spell
> "long long" as "__int64", others don't support it at all etc etc.
>
>>I believe unsigned long long should be highest possible integer type ?
>>Or am I wrong ?
>
> You're right, but the size of long long varies from platform to
> platform

Yes, but if you want the biggest unsigned integer type, you have to
accept that its size is going to vary.

If you want a type whose size *doesn't* vary, you want
something like uint64_t (and if you need this in C90, see
<http://www.lysator.liu.se/c/q8/>). (I think most C90 implementations
these days provide 64-bit integer types under some name.)

BTW, C99 defines uintmax_t for precisely this purpose.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Mark McIntyre

unread,
Jan 28, 2006, 3:42:20 PM1/28/06
to
On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>Mark McIntyre <markmc...@spamcop.net> writes:
>> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
>> "junky_...@yahoo.co.in" <junky_...@yahoo.co.in> wrote:
>>
>>>I believe unsigned long long should be highest possible integer type ?
>>>Or am I wrong ?
>>
>> You're right, but the size of long long varies from platform to
>> platform
>
>Yes, but if you want the biggest unsigned integer type, you have to
>accept that its size is going to vary.

... which was my point.

Keith Thompson

unread,
Jan 28, 2006, 4:31:09 PM1/28/06
to
Mark McIntyre <markmc...@spamcop.net> writes:
> On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
> <ks...@mib.org> wrote:
>>Mark McIntyre <markmc...@spamcop.net> writes:
>>> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
>>> "junky_...@yahoo.co.in" <junky_...@yahoo.co.in> wrote:
>>>
>>>>I believe unsigned long long should be highest possible integer type ?
>>>>Or am I wrong ?
>>>
>>> You're right, but the size of long long varies from platform to
>>> platform
>>
>>Yes, but if you want the biggest unsigned integer type, you have to
>>accept that its size is going to vary.
>
> ... which was my point.

Then I'm confused. junky_fellow's question was:

But if this is the case (ie we need the biggest possible unsigned
integer to hold offset ) then why not declare unsigned long long
offset

and you replied:

Because then its size would vary from platform to platform, and on
a c90 implementation it would be an error.

The second point is valid (except for the many C90 implementations
that provide "long long" as an extension), but I don't see what you're
getting at with the first point. If you want the biggest possible
unsigned integer, its size *will* vary from platform to platform, but
you presented the variation in size as a reason not to use "unsigned
long long".

(And C99 allows extended integer types, so unsigned long long isn't
necessarily the longest unsigned integer type. unsigned long long
could be 64 bits, and uintmax_t could be 128 bits.)

Either you want unsigned long long (whose size will vary, and which
may not exist in a C90 implementation), or you want the largest
unsigned integer type (whose size will vary), or you want an unsigned
type that's exactly 64 bits (which probably exists, but it's not
guaranteed in either C90 or C99). For the second and third cases, a
typedef is reasonable -- and C99's <stdint.h> provides uintmax_t and
uint64_t, respectively. For the first case, if you specifically want
unsigned long long for some reason, a typedef would be silly. Mark,
without going back to the question of what point you were making
upthread, is there anything in this paragraph you disagree with?

Jordan Abel

unread,
Jan 28, 2006, 6:48:29 PM1/28/06
to
On 2006-01-28, junky_...@yahoo.co.in <junky_...@yahoo.co.in> wrote:
> I was looking at the source code of linux or open BSD. What I found
> that lots of typedefs
> were used. For example, consider the offset in a file. It was declared
> as
> off_t offset;
> and off_t is typedefed as
> typedef long off_t;

On your system. On my system it's long long.

Jordan Abel

unread,
Jan 28, 2006, 6:50:00 PM1/28/06
to
On 2006-01-28, Keith Thompson <ks...@mib.org> wrote:
> Mark McIntyre <markmc...@spamcop.net> writes:
>> On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
>> <ks...@mib.org> wrote:
>>>Mark McIntyre <markmc...@spamcop.net> writes:
>>>> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
>>>> "junky_...@yahoo.co.in" <junky_...@yahoo.co.in> wrote:
>>>>
>>>>>I believe unsigned long long should be highest possible integer type ?
>>>>>Or am I wrong ?
>>>>
>>>> You're right, but the size of long long varies from platform to
>>>> platform
>>>
>>>Yes, but if you want the biggest unsigned integer type, you have to
>>>accept that its size is going to vary.
>>
>> ... which was my point.
>
> Then I'm confused. junky_fellow's question was:
>
> But if this is the case (ie we need the biggest possible unsigned
> integer to hold offset ) then why not declare unsigned long long
> offset
>
> and you replied:
>
> Because then its size would vary from platform to platform, and on
> a c90 implementation it would be an error.

Regardless, there's a factual problem. The "offset" (assuming it is
posix off_t) is used in places where it must be negative, and thus
should not be unsigned anything. the original post said long, not
unsigned long.

Chris Torek

unread,
Jan 29, 2006, 2:54:30 AM1/29/06
to
In article <1138434930.4...@g43g2000cwa.googlegroups.com>

junky_...@yahoo.co.in <junky_...@yahoo.co.in> wrote:
>I wanted to know what advantage do we get by typedefs?

In many ways, none at all.

In one somewhat important way, a fairly big one.

The underlying problem / solution here is "abstraction".

Fundamentally, abstraction is all about removing unnecessary
detail, while retaining necessary detail. (Not all abstractions
*succeed* at this task, mind.) This is really the heart of
most (maybe even all) computer programming.

The real world is ineluctably complex. Computer programs tend to
deal with simplified models. Even so, the simplified models are
often (maybe even usually) sufficiently complicated that programmers
cannot debug them without breaking them down even further. This
is why we use higher level languages -- it is at least one reason,
and I think one can argue that it is really the only reason, that
we do not write everything in machine code -- and also why we
break large programs into functions and (in langauges like C)
data structures.

C has a number of mostly-concrete data types: char, short, int,
and long (and in C99 long long) and their unsigned variants; float,
double, and long double; and pointers. (C99 adds complex number
types. C also has "void", but this is mostly a degenerate case,
and "enum", but enum is just a special case of "integral".) These
types are already somewhat abstracted from the underlying machine;
for instance, many microprocessors do not have hardware support
(or full support) for 64 or even 32 bit integral types, and many
only offer floating-point as an option (with a coprocessor) and/or
need software assistance. Still, these types are generally "close
to the metal", as the phrase goes: most CPUs implement most of them
mostly in hardware (although complex numbers rarely have direct
hardware support).

In addition to these (and derived types -- which actually include
all the pointer types as well as arrays; note also that "pointer
to function returning T" is a data type, even though it points to
a function type), C has the "user-defined abstract data type",
which is spelled "struct". Whenever you declare or define a new
struct, you get a new type. This new type is not compatible with
any existing type:

struct one { int val; } a;
struct two { int val; } b;
...
a = b; /* ERROR, type mismatch */

User-defined types give you everything you need to make new,
compiler-checked abstractions. A subroutine or function is also
an abstraction, but unless you make it use or return a user-defined
data type, it is possible to apply it to data of an inappropriate
type. Consider, for instance, a subroutine that checks a
temperature, which you might use in the control system for a
nuclear reactor:

void check_temperature(double the_value) { ... }

If you are only checking "any old double" (as in this case), it is
possible to call this with a length or pressure measurement by
accident:

double x;
...
x = measure_something(...); /* actually returns a pressure */
...
check_temperature(x);

A C compiler is not required to complain, and it would be surprising
to find one that does. Make separate "temperature" and "pressure"
data types, however, and we get:

void check_temperature(struct temperature the_value) { ... }
...
struct pressure x;
...
x = measure_something(...);
...
check_temperature(x);

Now the compiler *is* required to complain.

The problem with C's "typedef" is that it does *not* actually define
types. Instead, it just defines an alias for some existing type.
The aliases can be mixed freely. Thus if we try to use:

typedef double temperature;
typedef double pressure;

we lose many of the advantages of abstract data types.

At the same time, however, typedefs *do* give us a level of
indirection. Consider ANSI/ISO C "size_t", for instance. The
Standard tells us that size_t is an unsigned integral type that
holds the size (in bytes, which C calls "char"s) of an object. In
general, size_t is an alias for one of three types: unsigned int,
unsigned long, or unsigned long long. (Technically it could be an
alias for unsigned char or unsigned short, or even one of the weird
"extra" types allowed in C99, but in practice this does not occur.)

This "level of indirection" acts as a sort of "leaky" abstract
type. It fails to provide compile-time type-checking; we can use
the wrong types all over the place and never even notice. But *if*
we manage to use it correctly, it does insulate us from any changes
needed when porting code from one machine to another. If size_t
should be "unsigned int" on one 64-bit machine, but "unsigned long"
on another, it *can* be. We can -- if we are sufficiently careful
-- avoid assuming that it is either one or the other.

The two things typedef gives you, that struct does not, are:

- you do not need to write out the word "struct" each time, and

- you can make the type-name a synonym for a fundamental, built
in type (like "long" or "unsigned char"), rather than a
user-defined abstract type.

In C89 (but not C99), that second point is significant, because
there is no way in C89 to write constants of user-defined type.
In C99 we can do things like this:

struct pressure { double val; };
#define PRESSURE_UNKNOWN ((struct pressure){-1})
...
struct pressure p = estimate_pressure(...);
...
some_loop_construct {
...
if (some_condition)
p = PRESSURE_UNKNOWN; /* make sure we measure it below */
...
if (p == PRESSURE_UNKNOWN) ...
...
}

(Of course, in C89 you can always write macros to deal with
this, e.g., #define SET_TO_UNKNOWN(pp) ((pp)->val = -1), but
this is hardly elegant.)

Structure values are often implemented relatively inefficiently.
If this is the case for any particular situation / compiler, we
can use typedef to get a "checked system", and then recompile to
get a (presumably faster) "unchecked" version:

#ifdef SLEAZE
typedef double pressure;
#define MK_CONSTANT(t, val) ((t)(val))
#else
typedef struct pressure pressure;
struct pressure { double val; };
#define MK_CONSTANT(t, val) ((t){val})
#endif
...
pressure estimate_pressure(...);
#define PRESSURE_UNKNOWN MK_CONSTANT(pressure, -1)

Now we simply need to "#define SLEAZE" to get the "unchecked"
version. (The MK_CONSTANT trick above is again C99-dependent.)
--
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.

Mark McIntyre

unread,
Jan 29, 2006, 6:22:17 AM1/29/06
to
On Sat, 28 Jan 2006 21:31:09 GMT, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>
>Then I'm confused. junky_fellow's question was:
>
> But if this is the case (ie we need the biggest possible unsigned
> integer to hold offset ) then why not declare unsigned long long
> offset
>
>and you replied:
>
> Because then its size would vary from platform to platform, and on
> a c90 implementation it would be an error.

>but I don't see what you're


>getting at with the first point. If you want the biggest possible
>unsigned integer, its size *will* vary from platform to platform, but
>you presented the variation in size as a reason not to use "unsigned
>long long".

My point was that it will vary, and is thus a nonportable construct in
terms of say file access. If all you care about is one platform, then
no problem.
But this thread was about why one would use typedefs, and one reason
is to keep such platform specific stuff in a single place.

Keith Thompson

unread,
Jan 29, 2006, 3:36:40 PM1/29/06
to
Mark McIntyre <markmc...@spamcop.net> writes:
> On Sat, 28 Jan 2006 21:31:09 GMT, in comp.lang.c , Keith Thompson
> <ks...@mib.org> wrote:
>>Then I'm confused. junky_fellow's question was:
>>
>> But if this is the case (ie we need the biggest possible unsigned
>> integer to hold offset ) then why not declare unsigned long long
>> offset
>>
>>and you replied:
>>
>> Because then its size would vary from platform to platform, and on
>> a c90 implementation it would be an error.
>
>>but I don't see what you're
>>getting at with the first point. If you want the biggest possible
>>unsigned integer, its size *will* vary from platform to platform, but
>>you presented the variation in size as a reason not to use "unsigned
>>long long".
>
> My point was that it will vary, and is thus a nonportable construct in
> terms of say file access. If all you care about is one platform, then
> no problem.
> But this thread was about why one would use typedefs, and one reason
> is to keep such platform specific stuff in a single place.

Of course it will vary. junky_fellow *specifically* asked about "the
biggest possible unsigned integer". Maybe that's not the best thing
to use for a file offset -- and if that was your point, you might have
said so.

But *if* you need the biggest possible unsigned integer, for whatever
reason, it's perfectly sensible to use a typedef for it (or, in C99,
to use the existing uintmax_t). There could be any number of reasons
you'd want that. Of course, any code using it would have to allow for
the fact that the size will vary from one platform to another.

I notice that you snipped the direct question that I asked you.

Rod Pemberton

unread,
Jan 29, 2006, 7:00:39 PM1/29/06
to

<junky_...@yahoo.co.in> wrote in message
news:1138434930.4...@g43g2000cwa.googlegroups.com...


In response to:


> I wanted to know what advantage do we get by typedefs ?

I always seem to have problems with structures when they aren't typedef'd.
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. For example, say you have three
structures which should be nested but are separate. Now, you need some data
from the third structure. But, you have a raw buffer that corresponds to
the first structure, and, of course, contains the data for second and third
structures. How do you get to the data in the third structure? Using
typedef'd structures and casts, you can access the data from the third
structure in the raw buffer without allocating space for or filling in the
structures. You only need to allocate space for the raw buffer and
variables which are assigned data from the third structure. You have total
access to any data in the raw buffer, but you don't need to allocate and
fill any intermediate structures.


Rod Pemberton

Keith Thompson

unread,
Jan 29, 2006, 7:20:32 PM1/29/06
to
"Rod Pemberton" <dont...@bitbucket.cmm> writes:
> <junky_...@yahoo.co.in> wrote in message
> news:1138434930.4...@g43g2000cwa.googlegroups.com...
[...]

>> I wanted to know what advantage do we get by typedefs ?
[...]

> I always seem to have problems with structures when they aren't typedef'd.
> 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. For example, say you have three
> structures which should be nested but are separate. Now, you need some data
> from the third structure. But, you have a raw buffer that corresponds to
> the first structure, and, of course, contains the data for second and third
> structures. How do you get to the data in the third structure? Using
> typedef'd structures and casts, you can access the data from the third
> structure in the raw buffer without allocating space for or filling in the
> structures. You only need to allocate space for the raw buffer and
> variables which are assigned data from the third structure. You have total
> access to any data in the raw buffer, but you don't need to allocate and
> fill any intermediate structures.

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" -- which is why I prefer the simpler:

struct foo {
/* member declarations */
};

Can you provide an example where the typedef gives you a real
advantage? (Saving keystrokes doesn't count as a "real advantage".)

I'm not sure I understand your example anyway; the use of casts always
makes me nervous. If you have "three structures which should be
nested but are separate", what's stopping you from nesting them?
But in any case, a cast to "struct foo*" is as valid as a cast to
"foo_t*".

CBFalconer

unread,
Jan 29, 2006, 6:47:19 PM1/29/06
to
Keith Thompson wrote:
>
... snip ...

>
> I notice that you snipped the direct question that I asked you.

As a general principle I suggest that snipping should be done in
units of paragraphs. This reduces the alteration of meaning by
quoting out of context. This might also have the desirable side
effect of encouraging reasonable paragraphing.

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943


Keith Thompson

unread,
Jan 29, 2006, 10:19:44 PM1/29/06
to
CBFalconer <cbfal...@yahoo.com> writes:
> Keith Thompson wrote:
>>
> ... snip ...
>>
>> I notice that you snipped the direct question that I asked you.
>
> As a general principle I suggest that snipping should be done in
> units of paragraphs. This reduces the alteration of meaning by
> quoting out of context. This might also have the desirable side
> effect of encouraging reasonable paragraphing.

I think the snipping was done in units of paragraphs. The question
was part of an entire paragraph that was snipped. (Not that he's
under any obligation to answer any particular question, of course.)

Rod Pemberton

unread,
Jan 29, 2006, 10:29:37 PM1/29/06
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnirs2s...@nuthaus.mib.org...

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;


This is same as the following sequence of 'pseudo' code. We take the
address of buf:
'&buf'

which is then cast as a 'partition boot sector':
'(partition_boot_sector *)&buf'

Now that we have a 'partition boot sector', we locate the 'bios parameter
block':
'partition_boot_sector->bpb'

We then cast the address of the 'bios parameter block' as a 'bios parameter
block':
'(bios_parameter_block *)&(partition_boot_sector->bpb)'
This address should be something like &buf+12 or buf[12].

Now that we have a 'bios parameter block', we locate the number of heads:
'bios_parameter_block->number_of_heads'
This address of this data should be something lik &buf+12+16 or buf[28].

(The structs are big so I'll direct you to Ralph Brown's Interrupt list for
their layout.)

As long as the layout of the structures are correct (i.e., packed, if
necessary), you can get the data you want without dealing with any offsets
or copying data to/from structures etc.


Hope that helps.

Rod Pemberton

Keith Thompson

unread,
Jan 29, 2006, 11:56:55 PM1/29/06
to

(Please don't quote signatures.)

[snip]

> 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;
>
>
> This is same as the following sequence of 'pseudo' code. We take the
> address of buf:
> '&buf'
>
> which is then cast as a 'partition boot sector':
> '(partition_boot_sector *)&buf'
>
> Now that we have a 'partition boot sector', we locate the 'bios parameter
> block':
> 'partition_boot_sector->bpb'
>
> We then cast the address of the 'bios parameter block' as a 'bios parameter
> block':
> '(bios_parameter_block *)&(partition_boot_sector->bpb)'
> This address should be something like &buf+12 or buf[12].
>
> Now that we have a 'bios parameter block', we locate the number of heads:
> 'bios_parameter_block->number_of_heads'
> This address of this data should be something lik &buf+12+16 or buf[28].

[snip]
> Hope that helps.

Um, not really.

It's hard to tell without seeing the actual code, but I presume
bios_parameter_block and partition_boot_sector are typedefs for some
struct types. Let's assume they're called "struct bios_parameter_block"
and "struct partition_boot_sector".

Then your statement

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

could as easily be written

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

As I said, there's nothing you can do with typedefs for struct types
that you can't do just as easily with the struct types themselves.

Chris Torek

unread,
Jan 29, 2006, 11:59:09 PM1/29/06
to
>> "Rod Pemberton" <dont...@bitbucket.cmm> 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" <ks...@mib.org> wrote in message
>news:lnirs2s...@nuthaus.mib.org...

>> 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-...@news.infowest.com>


Rod Pemberton <dont...@bitbucket.cmm> 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 :-)

John Bode

unread,
Jan 30, 2006, 12:00:00 PM1/30/06
to

There are several reasons for doing this.

1. At some point in the future, a "long" may no longer be adequate for
representing offset values, and all offsets will need to be long long
(or some other type). By creating the typedef, you only need to make
that change in one place; i.e., change

typedef long off_t;

to

typedef long long off_t;

This is preferable to searching the source code for all offset
variables (which may or may not be named "offset") and changing their
definitions individually.

2. It allows you to implement the same types differently across
different platforms, depending on what's the most efficient or
practical for that platform. A 32-bit offset type would be wasteful on
a 16-bit platform, whereas it wouldn't be sufficient for a 64-bit
platform. Then you can have segmented architectures, were the offset
can be defined as a page number as well as displacement. Again, you
only have to make the change in one place, as opposed to finding and
changing every offset variable.

3. Sort of as a corollary to 2, it allows you to hide certain
implementation details from other programmers. You probably don't want
people making assumptions about the size of the offset available to
them, precisely because that value can change from platform to
platform.

tedu

unread,
Jan 30, 2006, 3:14:45 PM1/30/06
to
John Bode wrote:

> 3. Sort of as a corollary to 2, it allows you to hide certain
> implementation details from other programmers. You probably don't want
> people making assumptions about the size of the offset available to
> them, precisely because that value can change from platform to
> platform.

or the opposite, since off_t is intended to be 64-bit (depending on
OS), regardless of the underlying hardware.

Jordan Abel

unread,
Jan 30, 2006, 3:28:19 PM1/30/06
to

Says who?

Open Group Base Specifications Issue 6:

off_t
Used for file sizes.

All of the types shall be defined as arithmetic types of an appropriate
length, with the following exceptions: [Not off_t]

Additionally:
* blkcnt_t and off_t shall be signed integer types.

tedu

unread,
Jan 30, 2006, 4:07:48 PM1/30/06
to
Jordan Abel wrote:
> On 2006-01-30, tedu <t...@zeitbombe.org> wrote:
> > John Bode wrote:
> >
> >> 3. Sort of as a corollary to 2, it allows you to hide certain
> >> implementation details from other programmers. You probably don't want
> >> people making assumptions about the size of the offset available to
> >> them, precisely because that value can change from platform to
> >> platform.
> >
> > or the opposite, since off_t is intended to be 64-bit (depending on
> > OS), regardless of the underlying hardware.
>
> Says who?
>
> Open Group Base Specifications Issue 6:
>
> off_t
> Used for file sizes.

the OP mentioned openbsd; that's one. as i said, it depends on the OS,
but some people think it's more consistent to be able to address
"large" files even on 32 bit platforms than to always have off_t be a
native machine type, so that programs behave more or less consistently
on that OS.

the point was that sometimes typedef is used to make a type have a
fixed size, in contrast to a typedef like size_t that deliberately
varies in size.

Jordan Abel

unread,
Jan 30, 2006, 5:29:33 PM1/30/06
to
On 2006-01-30, tedu <t...@zeitbombe.org> wrote:
> Jordan Abel wrote:
>> On 2006-01-30, tedu <t...@zeitbombe.org> wrote:
>> > John Bode wrote:
>> >
>> >> 3. Sort of as a corollary to 2, it allows you to hide certain
>> >> implementation details from other programmers. You probably don't want
>> >> people making assumptions about the size of the offset available to
>> >> them, precisely because that value can change from platform to
>> >> platform.
>> >
>> > or the opposite, since off_t is intended to be 64-bit (depending on
>> > OS), regardless of the underlying hardware.
>>
>> Says who?
>>
>> Open Group Base Specifications Issue 6:
>>
>> off_t
>> Used for file sizes.
>
> the OP mentioned openbsd; that's one. as i said, it depends on the OS,
> but some people think it's more consistent to be able to address
> "large" files even on 32 bit platforms than to always have off_t be a
> native machine type, so that programs behave more or less consistently
> on that OS.

Yeah but who says it can't be 128 bits? Or 96 bits?

[besides, i believe linux/x86, for one, supports two different APIs, and the
default one is 32 bits]

Mark McIntyre

unread,
Jan 30, 2006, 5:54:13 PM1/30/06
to
On Sun, 29 Jan 2006 20:36:40 GMT, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>Of course it will vary. junky_fellow *specifically* asked about "the
>biggest possible unsigned integer".

Ain't no such thing. I guess /that/ was my point.

>I notice that you snipped the direct question that I asked you.

Did I? I didn't even notice it I'm afraid.

Keith Thompson

unread,
Jan 30, 2006, 6:10:59 PM1/30/06
to
Mark McIntyre <markmc...@spamcop.net> writes:
> On Sun, 29 Jan 2006 20:36:40 GMT, in comp.lang.c , Keith Thompson
> <ks...@mib.org> wrote:
>
>>Of course it will vary. junky_fellow *specifically* asked about "the
>>biggest possible unsigned integer".
>
> Ain't no such thing. I guess /that/ was my point.

Of course there is. What do you think uintmax_t is for?

Mark McIntyre

unread,
Jan 31, 2006, 7:02:41 PM1/31/06
to
On Mon, 30 Jan 2006 23:10:59 GMT, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>Mark McIntyre <markmc...@spamcop.net> writes:
>> On Sun, 29 Jan 2006 20:36:40 GMT, in comp.lang.c , Keith Thompson
>> <ks...@mib.org> wrote:
>>
>>>Of course it will vary. junky_fellow *specifically* asked about "the
>>>biggest possible unsigned integer".
>>
>> Ain't no such thing. I guess /that/ was my point.
>
>Of course there is. What do you think uintmax_t is for?

And whats its value? Please give a portable answer.

Jordan Abel

unread,
Jan 31, 2006, 7:31:54 PM1/31/06
to
On 2006-02-01, Mark McIntyre <markmc...@spamcop.net> wrote:
> On Mon, 30 Jan 2006 23:10:59 GMT, in comp.lang.c , Keith Thompson
> <ks...@mib.org> wrote:
>
>>Mark McIntyre <markmc...@spamcop.net> writes:
>>> On Sun, 29 Jan 2006 20:36:40 GMT, in comp.lang.c , Keith Thompson
>>> <ks...@mib.org> wrote:
>>>
>>>>Of course it will vary. junky_fellow *specifically* asked about "the
>>>>biggest possible unsigned integer".
>>>
>>> Ain't no such thing. I guess /that/ was my point.
>>
>>Of course there is. What do you think uintmax_t is for?
>
> And whats its value? Please give a portable answer.

Its value is the biggest possible unsigned integer type. Its biggest
possible value is UINTMAX_MAX.

> Mark McIntyre

Keith Thompson

unread,
Jan 31, 2006, 8:29:12 PM1/31/06
to
Mark McIntyre <markmc...@spamcop.net> writes:
> On Mon, 30 Jan 2006 23:10:59 GMT, in comp.lang.c , Keith Thompson
> <ks...@mib.org> wrote:
>>Mark McIntyre <markmc...@spamcop.net> writes:
>>> On Sun, 29 Jan 2006 20:36:40 GMT, in comp.lang.c , Keith Thompson
>>> <ks...@mib.org> wrote:
>>>
>>>>Of course it will vary. junky_fellow *specifically* asked about "the
>>>>biggest possible unsigned integer".
>>>
>>> Ain't no such thing. I guess /that/ was my point.
>>
>>Of course there is. What do you think uintmax_t is for?
>
> And whats its value? Please give a portable answer.

What do you mean "whats its value"? It's a type. What's the value of
int?

If you're asking about the maximum value of the type, you know as well
as I do that there is no portable answer. I never claimed that there
was *or that there should be*.

If you mean "value" in a more colloquial sense, uintmax_t can be
*very* valuable if it happens to be what you need.

You've been arguing (I think) that it's inappropriate to use a typedef
for something whose size can vary from one platform to another. Do
you believe that uintmax_t should not have been included in the C
standard? What about size_t? Or should size_t have been required to
have the same size across all implementations?

I would appreciate a direct answer to at least one of these questions.

0 new messages