advantage of using typedefs

Discussion in 'C Programming' started by junky_fellow@yahoo.co.in, Jan 28, 2006.

  1. Guest

    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 ....
    , Jan 28, 2006
    #1
    1. Advertising

  2. 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
    Emmanuel Delahaye, Jan 28, 2006
    #2
    1. Advertising

  3. Guest

    Emmanuel Delahaye wrote:
    > 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.
    >


    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 ?
    , Jan 28, 2006
    #3
  4. On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
    "" <> 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 =----
    Mark McIntyre, Jan 28, 2006
    #4
  5. "Thad Smith" <> wrote in message
    news:43db9067$0$81213$...
    > 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
    William J. Leary Jr., Jan 28, 2006
    #5
  6. Thad Smith Guest

    wrote:
    > Emmanuel Delahaye wrote:
    >
    >> 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
    Thad Smith, Jan 28, 2006
    #6
  7. Mark McIntyre <> writes:
    > On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
    > "" <> 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) <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.
    Keith Thompson, Jan 28, 2006
    #7
  8. On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
    <> wrote:

    >Mark McIntyre <> writes:
    >> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
    >> "" <> 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.

    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 =----
    Mark McIntyre, Jan 28, 2006
    #8
  9. Mark McIntyre <> writes:
    > On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
    > <> wrote:
    >>Mark McIntyre <> writes:
    >>> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
    >>> "" <> 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?

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Jan 28, 2006
    #9
  10. Jordan Abel Guest

    On 2006-01-28, <> 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.

    >
    > 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 ....
    >
    Jordan Abel, Jan 28, 2006
    #10
  11. Jordan Abel Guest

    On 2006-01-28, Keith Thompson <> wrote:
    > Mark McIntyre <> writes:
    >> On Sat, 28 Jan 2006 19:32:56 GMT, in comp.lang.c , Keith Thompson
    >> <> wrote:
    >>>Mark McIntyre <> writes:
    >>>> On 28 Jan 2006 00:50:55 -0800, in comp.lang.c ,
    >>>> "" <> 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.
    Jordan Abel, Jan 28, 2006
    #11
  12. Chris Torek Guest

    In article <>
    <> 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.
    Chris Torek, Jan 29, 2006
    #12
  13. On Sat, 28 Jan 2006 21:31:09 GMT, in comp.lang.c , Keith Thompson
    <> 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.
    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 =----
    Mark McIntyre, Jan 29, 2006
    #13
  14. Mark McIntyre <> writes:
    > On Sat, 28 Jan 2006 21:31:09 GMT, in comp.lang.c , Keith Thompson
    > <> 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.

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Jan 29, 2006
    #14
  15. CBFalconer Guest

    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
    CBFalconer, Jan 29, 2006
    #15
  16. <> wrote in message
    news:...
    > 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 ....



    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
    Rod Pemberton, Jan 30, 2006
    #16
  17. "Rod Pemberton" <> writes:
    > <> wrote in message
    > news:...

    [...]
    >> 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*".

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Jan 30, 2006
    #17
  18. CBFalconer <> 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.)

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Jan 30, 2006
    #18
  19. "Keith Thompson" <> wrote in message
    news:...
    > "Rod Pemberton" <> writes:
    > > <> wrote in message
    > > news:...

    > [...]
    > >> 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*".
    >
    > --
    > Keith Thompson (The_Other_Keith)

    <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.


    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
    Rod Pemberton, Jan 30, 2006
    #19
  20. "Rod Pemberton" <> writes:
    > "Keith Thompson" <> wrote in message
    > news:...
    >> "Rod Pemberton" <> writes:
    >> > <> wrote in message
    >> > news:...

    >> [...]
    >> >> 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".)


    (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.

    --
    Keith Thompson (The_Other_Keith) <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.
    Keith Thompson, Jan 30, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ashish
    Replies:
    3
    Views:
    3,994
    Naveen K Kohli
    Sep 7, 2004
  2. Replies:
    1
    Views:
    2,250
    Robert Maas, see http://tinyurl.com/uh3t
    Jun 11, 2005
  3. Dave
    Replies:
    4
    Views:
    769
    Andrey Tarasevich
    Dec 5, 2003
  4. pyramus
    Replies:
    3
    Views:
    505
    Victor Bazarov
    Nov 29, 2005
  5. Chris Fairles
    Replies:
    2
    Views:
    339
    Gennaro Prota
    Jun 26, 2007
Loading...

Share This Page