Cast to a struct?

Discussion in 'C Programming' started by Jack, Jul 6, 2006.

  1. Jack

    Jack Guest

    Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
    4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
    contain information independent of each other. Is there a direct way
    to perform this cast? If not, is there way in C++ to do it?

    For example, I would like my function test() to work the way it is
    coded below. It produces a compiler error though:

    #include <pshpack2.h> // 16-bit padding

    // My 4-byte struct
    typedef struct _mystruct_t
    {
    unsigned short cx;
    unsigned short cy;
    } mystruct_t;

    #include <poppack.h>

    mystruct_t test()
    {
    unsigned int n = 0xffff0001;
    return (mystruct_t)n;
    }

    int main()
    {
    mystruct_t s = test();
    return 0;
    }
    Jack, Jul 6, 2006
    #1
    1. Advertising

  2. Jack

    Ian Collins Guest

    Jack wrote:
    > Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
    > 4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
    > contain information independent of each other. Is there a direct way
    > to perform this cast? If not, is there way in C++ to do it?
    >

    Shouldn't that be C?

    If you want to overlay types of the same size, use a union.

    --
    Ian Collins.
    Ian Collins, Jul 6, 2006
    #2
    1. Advertising

  3. Jack <> writes:
    > Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
    > 4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
    > contain information independent of each other. Is there a direct way
    > to perform this cast?


    No. Neither the source expression nor the target type of a cast is
    allowed to be a struct (except that any expression can be cast to
    void).

    > If not, is there way in C++ to do it?


    How would we know that?

    > For example, I would like my function test() to work the way it is
    > coded below. It produces a compiler error though:
    >
    > #include <pshpack2.h> // 16-bit padding
    >
    > // My 4-byte struct
    > typedef struct _mystruct_t
    > {
    > unsigned short cx;
    > unsigned short cy;
    > } mystruct_t;
    >
    > #include <poppack.h>
    >
    > mystruct_t test()
    > {
    > unsigned int n = 0xffff0001;
    > return (mystruct_t)n;
    > }
    >
    > int main()
    > {
    > mystruct_t s = test();
    > return 0;
    > }


    I think you've misunderstood what a cast is for.

    A cast specifies a type conversion. A conversion takes the *value* of
    a source expression, and yields a value of another type (or the same
    type); the result has some close relationship to the original value
    (for example, it may be the same value in the case of a numeric
    conversion). A conversion operates on values, not representations; it
    doesn't just reinterpret the bits of the representation of the source.

    For example, the cast expression (double)42 yields the value 42.0; the
    int value 42 and the double value 42.0 have the same mathematical
    value, but completely different representations.

    (Pointer conversions typically work by reinterpreting bits, but only
    because that makes sense in terms of the values.)

    Looking at your code:

    Avoid identifiers starting with '_'. Some of them are reserved to the
    implementation in some or all contexts. It's much easier to avoid
    such identifiers altogether than to remember the special cases in
    which you can get away with using them.

    Personally, I wouldn't use a typedef at all; I'd just declare the type
    as "struct mystruct_t", and refer to it as "struct mystruct_t". But
    if you prefer to use the typedef, it perfectly legal.

    You're assuming, I think, that unsigned short is exactly 16 bits, and
    unsigned int is exactly 32 bits. If the code isn't intended to be
    portable, that may be acceptable; otherwise your code is likely to
    break on systems where that isn't the case. (You also can't portably
    assume that unsigned int is exactly twice as big as unsigned short;
    I've worked on systems where it's the same size, and on others where
    it's four times as big.)

    What is the conversion supposd to do? I'm guessing you want to store
    0xffff in one of the members and 0x0001 in the other, but which is
    which? If you copy the value directly (using memcpy, or a union, or
    pointer tricks), the results will vary depending on whether your
    platform is big-endian or little-endian. You'll need to decide
    exactly what you want to do before you can figure out the best way to
    do it.

    Finally, <pshpack2.h> and <poppack.h> are non-standard headers, and I
    don't know what you mean by "16-bit padding".

    --
    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, Jul 6, 2006
    #3
  4. Jack

    MQ Guest

    I
    >
    > If you want to overlay types of the same size, use a union.
    >


    Wouldn't that depend upon the implementation of the compiler/platform,
    in terms of how it represents the data type. It sounds like the OP
    wants to do something like:

    struct C
    {
    short hiword;
    short loword;
    };
    union A
    {
    int b
    struct C c;
    };

    would this not possibly behave differently depending on whether it was
    compiled on a little-endain or big-endian machine?
    MQ, Jul 6, 2006
    #4
  5. Jack

    Flash Gordon Guest

    MQ wrote:
    > I
    >> If you want to overlay types of the same size, use a union.

    >
    > Wouldn't that depend upon the implementation of the compiler/platform,
    > in terms of how it represents the data type. It sounds like the OP
    > wants to do something like:
    >
    > struct C
    > {
    > short hiword;
    > short loword;
    > };
    > union A
    > {
    > int b
    > struct C c;
    > };
    >
    > would this not possibly behave differently depending on whether it was
    > compiled on a little-endain or big-endian machine?


    Yes, you are correct. Even worse, the compiler might insert padding
    between hiword and loword so even on a system where short is half the
    size of int the struct could be longer than an int.

    Depending on what the OP actually wants to achieve, either using a
    pointer to unsigned char pointing at the int or using shifting and
    masking would be better. With the shifting/masking you are best working
    with unsigned int otherwise you can get unexpected results.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Jul 6, 2006
    #5
  6. On Thu, 6 Jul 2006 02:01:19 UTC, Jack <> wrote:

    > Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
    > 4-byte struct?


    No.

    Sometimes the HIWORD and LOWORD of a 4-byte value
    > contain information independent of each other. Is there a direct way
    > to perform this cast? If not, is there way in C++ to do it?


    You are leaving the lands of standard C. What you tries is higly
    implementation specific and has nothing to do with standard C. Find a
    group that is related to your implementation and ask there for a way
    to get it - if it is possible.

    At least you gets an application that is in no way compatible - maybe
    not even between 2 different versions of the compiler you are using.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2 Deutsch ist da!
    Herbert Rosenau, Jul 6, 2006
    #6
  7. Jack

    SM Ryan Guest

    Jack <> wrote:
    # Is it possible to cast a 4-byte data type (e.g. an unsigned int) to a
    # 4-byte struct? Sometimes the HIWORD and LOWORD of a 4-byte value
    # contain information independent of each other. Is there a direct way
    # to perform this cast? If not, is there way in C++ to do it?
    #
    # For example, I would like my function test() to work the way it is
    # coded below. It produces a compiler error though:
    #
    # #include <pshpack2.h> // 16-bit padding
    #
    # // My 4-byte struct
    # typedef struct _mystruct_t
    # {
    # unsigned short cx;
    # unsigned short cy;
    # } mystruct_t;
    #
    # #include <poppack.h>
    #
    # mystruct_t test()
    # {
    # unsigned int n = 0xffff0001;
    # return (mystruct_t)n;
    # }

    You can use memcpy
    assert(sizeof n==sizeof(mystruct_t));
    mystruct_t N;
    memcpy(&N,&n,sizeof n);
    return N;

    # int main()
    # {
    # mystruct_t s = test();
    # return 0;
    # }
    #
    #

    --
    SM Ryan http://www.rawbw.com/~wyrmwif/
    I think that's kinda of personal; I don't think I should answer that.
    SM Ryan, Jul 6, 2006
    #7
    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. BestNews

    how to cast system.intptr to struct

    BestNews, Sep 2, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    4,725
    BestNews
    Sep 3, 2003
  2. MSG

    to cast or not to cast malloc ?

    MSG, Feb 6, 2004, in forum: C Programming
    Replies:
    38
    Views:
    1,063
    Dan Pop
    Feb 10, 2004
  3. EvilRix
    Replies:
    8
    Views:
    623
    Martin Dickopp
    Feb 14, 2004
  4. Chris Fogelklou
    Replies:
    36
    Views:
    1,358
    Chris Fogelklou
    Apr 20, 2004
  5. Pavel
    Replies:
    7
    Views:
    515
    Pavel
    Sep 19, 2010
Loading...

Share This Page