structure and union queries

Discussion in 'C Programming' started by Tagore, Apr 7, 2009.

  1. Tagore

    Tagore Guest

    hi,
    Please consider 2 programs below and queries assoicated with them:
    PROGRAM-1:
    #include<stdio.h>
    typedef union
    {
    float f1;
    float f2;
    int i;
    }sample;
    int main()
    {
    sample S={66};
    printf("%f %f %d",S.f1,S.f2,S.i);
    return 0;
    }

    OUTPUT:
    66.000000 66.000000 1115947008
    I feel myself unable to understand above output...I expected that as
    we are initializing S with 66 ,a integer, so It should print first two
    grabage value when printing floating values.and then print 66 but I
    found it otherwise here.

    PROGRAM-2:
    #include<stdio.h>
    typedef struct sample
    {
    int i;
    char a[10];
    }data;
    int main()
    {
    printf("%d", sizeof(data.a));
    return 0;
    }
    OUTPUT:
    In function 'main':
    Line 10: error: expected ')' before '.' token
    I expected output of this function to be 10 which is size of array
    a....but could not understand this error.

    Please help me regarding both queries
    Tagore, Apr 7, 2009
    #1
    1. Advertising

  2. Tagore

    Ze Long Guest

    Tagore 写é“:
    > hi,
    > Please consider 2 programs below and queries assoicated with them:
    > PROGRAM-1:
    > #include<stdio.h>
    > typedef union
    > {
    > float f1;
    > float f2;
    > int i;
    > }sample;
    > int main()
    > {
    > sample S={66};
    > printf("%f %f %d",S.f1,S.f2,S.i);
    > return 0;
    > }
    >
    > OUTPUT:
    > 66.000000 66.000000 1115947008
    > I feel myself unable to understand above output...I expected that as
    > we are initializing S with 66 ,a integer, so It should print first two
    > grabage value when printing floating values.and then print 66 but I
    > found it otherwise here.
    >
    > PROGRAM-2:
    > #include<stdio.h>
    > typedef struct sample
    > {
    > int i;
    > char a[10];
    > }data;
    > int main()
    > {
    > printf("%d", sizeof(data.a));
    > return 0;
    > }
    > OUTPUT:
    > In function 'main':
    > Line 10: error: expected ')' before '.' token
    > I expected output of this function to be 10 which is size of array
    > a....but could not understand this error.
    >
    > Please help me regarding both queries


    I don't know how does union work. But for the second program, you are
    defining a type named data, not a structure. The right way to do this is
    struct sample
    {
    int i;
    char a[10];
    }data;

    Notice there is not "typedef" in the first line.
    Ze Long, Apr 7, 2009
    #2
    1. Advertising

  3. Tagore

    jameskuyper Guest

    Tagore wrote:
    > hi,
    > Please consider 2 programs below and queries assoicated with them:
    > PROGRAM-1:
    > #include<stdio.h>
    > typedef union
    > {
    > float f1;
    > float f2;
    > int i;
    > }sample;
    > int main()
    > {
    > sample S={66};


    This code initializes S.f1 with a value of 66.0.

    > printf("%f %f %d",S.f1,S.f2,S.i);


    Any attempt to use the value of S.f2 or s.i at this point in the
    program has undefined behavior. The only member of a union that you
    can safely read is the member that was last written to.

    > return 0;
    > }
    >
    > OUTPUT:
    > 66.000000 66.000000 1115947008
    > I feel myself unable to understand above output...I expected that as
    > we are initializing S with 66 ,a integer, so It should print first two
    > grabage value when printing floating values.and then print 66 but I
    > found it otherwise here.


    The rule for initializing unions is that it's always the first member
    of the union that gets initialized, unless you specify otherwise (the
    ability to specify a different member is a C99 feature); the type of
    the initializer is irrelevant. The initializer is implicitly converted
    to the type of that member, as-if by assignment. In other words, your
    code is equivalent to

    sample S;
    S.f1 = 66;

    If you want to intialize i at the same time you define S, you can't do
    it in C90. In C99 you can write:
    sample S = {.i=66};

    > PROGRAM-2:
    > #include<stdio.h>
    > typedef struct sample
    > {
    > int i;
    > char a[10];
    > }data;
    > int main()
    > {
    > printf("%d", sizeof(data.a));


    This is the wrong format specifier to use. %d is for 'int'. The value
    of a sizeof expression has the type size_t, which is an unsigned
    integer type, and often one that is incompatible with 'int'. As a
    result, your printf() call has undefined behavior. See below for two
    different options for dealing with this problem.

    > return 0;
    > }
    > OUTPUT:
    > In function 'main':
    > Line 10: error: expected ')' before '.' token
    > I expected output of this function to be 10 which is size of array
    > a....but could not understand this error.


    You've defined 'data' to be a typedef for struct sample. You can write
    "sizeof(type)" or "sizeof expression", but data.a is neither a type
    nor an expression, it's a constraint violation. The left operand of
    the '.' operator must be an expression which has a struct or union
    type. 'data' is a type, not an expression. It IS a struct type; it is
    not an expression which has struct type.

    What you can do is write an expression whose type is the type of 'a':

    /* Use this form only for C90; unsigned long might not be big
    enough in C99. */
    printf("%lu", (unsigned long)sizeof ((data *)NULL)->a);

    /* Use this form only for C99; %z is not supported in C90. */
    printf("%zu", sizeof ((data *)NULL)->a);

    Those expressions look like they dereference null pointers, but the
    operand of a sizeof expression is not evaluated, (except in C99, and
    even then, only if the expression involves a VLA). The only thing
    "sizeof expression" does is determine what the type of the expression
    would be, if it were evaluated, so those expressions are perfectly
    safe.
    jameskuyper, Apr 7, 2009
    #3
  4. Tagore <> wrote:
    > Please consider 2 programs below and queries assoicated with them:
    > PROGRAM-1:
    > #include<stdio.h>
    > typedef union
    > {
    > float f1;
    > float f2;
    > int i;
    > }sample;
    > int main()
    > {
    > sample S={66};
    > printf("%f %f %d",S.f1,S.f2,S.i);
    > return 0;
    > }


    > OUTPUT:
    > 66.000000 66.000000 1115947008
    > I feel myself unable to understand above output...I expected that as
    > we are initializing S with 66 ,a integer, so It should print first two
    > grabage value when printing floating values.and then print 66 but I
    > found it otherwise here.


    No, just because there's an int in the union and the value you use
    for the initializaton is an int, the int member of the union isn't
    initialized automatically. To cite C standard: "A brace-enclosed
    initializer for a union object initializes the member that appears
    first in the declaration list of the union type." That means that
    in your case the 'f1' member of the union gets initialized (after
    converting 66 to a float value).

    Please also note that taking the value of the element of an union
    that wasn't the last one to be assigned a value to results in
    undefined behaviour - rather likely not a problem here with this
    test program but better avoided in a real program.

    > PROGRAM-2:
    > #include<stdio.h>
    > typedef struct sample
    > {
    > int i;
    > char a[10];
    > }data;
    > int main()
    > {
    > printf("%d", sizeof(data.a));
    > return 0;
    > }
    > OUTPUT:
    > In function 'main':
    > Line 10: error: expected ')' before '.' token
    > I expected output of this function to be 10 which is size of array
    > a....but could not understand this error.


    You can only apply 'sizeof' to either a type or a variable.
    Here 'data' would be a type, but 'data.a' isn't. On the other
    hand, if you would create an instance of the structure, like

    data mydata;

    you then could do

    printf( "%lu", ( unsigned long ) sizeof mydata.a q);

    Please note the cast of 'sizeof' and the use of "%lu" - what
    'sizeof' results in may not be (and often isn't) an int and
    lying to printf() (or other variadic functions) is never a
    good idea...
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Apr 7, 2009
    #4
  5. Tagore <> writes:
    > Please consider 2 programs below and queries assoicated with them:
    > PROGRAM-1:
    > #include<stdio.h>
    > typedef union
    > {
    > float f1;
    > float f2;
    > int i;
    > }sample;
    > int main()
    > {
    > sample S={66};
    > printf("%f %f %d",S.f1,S.f2,S.i);
    > return 0;
    > }
    >
    > OUTPUT:
    > 66.000000 66.000000 1115947008
    > I feel myself unable to understand above output...I expected that as
    > we are initializing S with 66 ,a integer, so It should print first two
    > grabage value when printing floating values.and then print 66 but I
    > found it otherwise here.


    The initializer initializes the *first* member of the union (not the
    first one that happens to match the expression's type). In this case,
    the int value 66 is converted to float, so S.f1 is 66.0. S.f2, since
    it's of the same type and occupies the same location in memory, also
    has the value 66.0. S.i has whatever int value corresponds to the
    float representation of 66.0 (in this case, apparently that's
    1115947008, or 0x42840000).

    > PROGRAM-2:
    > #include<stdio.h>
    > typedef struct sample
    > {
    > int i;
    > char a[10];
    > }data;
    > int main()
    > {
    > printf("%d", sizeof(data.a));
    > return 0;
    > }
    > OUTPUT:
    > In function 'main':
    > Line 10: error: expected ')' before '.' token
    > I expected output of this function to be 10 which is size of array
    > a....but could not understand this error.


    "data" is a type. You can't legally refer to data.a. You have to
    have an object or expression of type data; then you can refer to a
    member of that object or expression.

    To take a simpler example:

    typedef struct {
    int i;
    } my_type;

    my_type my_object;

    "my_type.i" is invalid, even as an argument to sizeof. "my_object.i"
    is valid; it refers to the i member of the object "my_object".

    (If "sizeof(my_type.i)" were legal, presumably it would give you the
    size of the i member of the type my_type. But it isn't, so it
    doesn't.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 7, 2009
    #5
  6. (Jens Thoms Toerring) writes:
    [...]
    > You can only apply 'sizeof' to either a type or a variable.


    Quibble: you can apply 'sizeof' either to a type (which must be in
    parentheses) or to an expression (specifically a unary-expression).
    For example, ``sizeof 42'' is legal, though 42 is neither a type nor a
    variable.

    > Here 'data' would be a type, but 'data.a' isn't.

    [...]

    The problem is that ``data.a'' is illegal, since the left operand of
    "." must be an expression, and data is a type name. The fact that
    it's being used as the operand of "sizeof" doesn't enter into it;
    ``data.a'' is illegal in any context.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 7, 2009
    #6
  7. Tagore

    Guest

    jameskuyper <> wrote:
    >
    > Any attempt to use the value of S.f2 or s.i at this point in the
    > program has undefined behavior. The only member of a union that you
    > can safely read is the member that was last written to.


    That was the rule in C90, but the rules in C99 recognize what really
    happens -- the existing bits are reinterpreted in the other type. Since
    f2 has the same type as the member that was last written to, the
    behavior of accessing it is completely defined. Accessing i is a bit
    more fluid; since the types are different, the existing bits may or may
    not be a valid representation. If they are, the behavior is well
    defined but the resulting value is unspecified. If not, all bets are
    off and you still get undefined behavior.
    --
    Larry Jones

    There's never enough time to do all the nothing you want. -- Calvin
    , Apr 8, 2009
    #7
  8. Tagore

    Flash Gordon Guest

    Joe Wright wrote:
    > wrote:
    >> jameskuyper <> wrote:
    >>> Any attempt to use the value of S.f2 or s.i at this point in the
    >>> program has undefined behavior. The only member of a union that you
    >>> can safely read is the member that was last written to.

    >>
    >> That was the rule in C90, but the rules in C99 recognize what really
    >> happens -- the existing bits are reinterpreted in the other type. Since
    >> f2 has the same type as the member that was last written to, the
    >> behavior of accessing it is completely defined. Accessing i is a bit
    >> more fluid; since the types are different, the existing bits may or may
    >> not be a valid representation. If they are, the behavior is well
    >> defined but the resulting value is unspecified. If not, all bets are
    >> off and you still get undefined behavior.

    >
    > I still don't get it.
    >
    > union s {
    > float f;
    > int i;
    > };
    >
    > union s S;
    > S.f = 66;
    >
    > The union S is essentially a 32-bit object with two names.


    On your implementation, possibly.

    > The above
    > assignment will set the bits of S like this..
    >
    > 01000010 10000100 00000000 00000000
    >
    > If I then printf("%d\n", S.i) I will get..
    >
    > 1115947008


    What if int is 64 bits but float only 32? What if int has a trap
    representation (as allowed by the standard) and you pick a float that
    happens to be represented by that particular bit pattern?

    > and then printf("%f\n", S.f) I will get..
    >
    > 66.000000
    >
    > I read S.i first, after assigning to S.f. Assuming float and int are
    > both 32 bits, what about the foregoing is undefined behavior? What can
    > possibly be wrong with it?


    You happen to use a float value that produces a bit pattern that is not
    a valid representation for an int as Lawrence said, i.e it is a trap
    representation. If there are no trap representations on your
    implementation then you won't get undefined behaviour.
    --
    Flash Gordon
    Flash Gordon, Apr 9, 2009
    #8
  9. Tagore

    jameskuyper Guest

    Joe Wright wrote:
    > wrote:

    ....
    > > That was the rule in C90, but the rules in C99 recognize what really
    > > happens -- the existing bits are reinterpreted in the other type. Since
    > > f2 has the same type as the member that was last written to, the
    > > behavior of accessing it is completely defined. Accessing i is a bit
    > > more fluid; since the types are different, the existing bits may or may
    > > not be a valid representation. If they are, the behavior is well
    > > defined but the resulting value is unspecified. If not, all bets are
    > > off and you still get undefined behavior.

    >
    > I still don't get it.
    >
    > union s {
    > float f;
    > int i;
    > };
    >
    > union s S;
    > S.f = 66;
    >
    > The union S is essentially a 32-bit object with two names. The above
    > assignment will set the bits of S like this..
    >
    > 01000010 10000100 00000000 00000000
    >
    > If I then printf("%d\n", S.i) I will get..
    >
    > 1115947008
    >
    > and then printf("%f\n", S.f) I will get..
    >
    > 66.000000
    >
    > I read S.i first, after assigning to S.f. Assuming float and int are
    > both 32 bits, what about the foregoing is undefined behavior?


    The fact that float and int are two different types.

    > What can
    > possibly be wrong with it?


    The C standard merely allows it to go wrong, because there are real
    implementations where it can go wrong. Potential problems include the
    possibility that a valid value for an 'int' might be represented by a
    bit pattern which represents an invalid value for a float (or vice
    versa). The C standard calls these bit patterns "trap
    representations", and any attempt to use an lvalue of a given type to
    retrieve the value of a piece of memory that contains a trap
    representation for that type has undefined behavior. There are real
    implementations where either 'int' or 'float' has trap
    representations, and where attempting to load an invalid bit pattern
    will produce seriously nasty consequences.

    Even on platforms without such exotic hardware, the fact that the
    standard says that this has undefined behavior indirectly opens up
    other possible failure modes. For instance, it gives implementations
    permission to perform optimizations that would otherwise be illegal.
    Example:

    S.f = 66.0F;
    // Compiler leaves a copy of 66.0 in a floating point register.
    S.i = -3;
    printf("%f\n", S.f)

    Since the behavior is undefined if you attempt to read S.f when the
    most recent write was to S.i, the compiler can perform an optimization
    based upon the assumption that you have NOT performed such a write
    (even though it's perfectly obvious that you have - the compiler is
    not required to pay attention to such things when the behavior is
    undefined). Specifically, it sees that the last time a value was
    written to 'S.f', that value was stored in a specific register, and
    that register has not been used for any other purpose since then.
    Since there is no code with defined behavior that could have changed
    the value of 'f' since that time, it can legally pass the value of
    66.0 that was stored in the floating point register to printf(). In
    other words, it's not required to notice that S.i occupies the same
    piece of memory as S.f when making this decision.

    This is a simple case, where such an "optimization" might seem
    perverse. However, it might significantly simplify the design of the
    compiler code that performs this optimization, if it doesn't have to
    bother checking for possibilities that have undefined behavior. As
    long as the optimization works correctly whenever the behavior is
    defined, such an optimization does not prevent a compiler from being
    conforming.

    This is an a example of a more general rule: whenever the C standard
    says that a given piece of code has undefined behavior, it gives
    implementations permission to simplify their compilers by not
    bothering to handle such code in the way you might naively think was
    correct. As a result, the simple fact that code has undefined behavior
    opens up failure modes in addition to the ones that were the original
    reason the committee decided to make the behavior undefined.
    jameskuyper, Apr 9, 2009
    #9
  10. Tagore

    CBFalconer Guest

    Joe Wright wrote:
    >

    .... snip ...
    >
    > I still don't get it.
    >
    > union s {
    > float f;
    > int i;
    > };
    >
    > union s S;
    > S.f = 66;
    >
    > The union S is essentially a 32-bit object with two names. The
    > above assignment will set the bits of S like this..
    >
    > 01000010 10000100 00000000 00000000
    >
    > If I then printf("%d\n", S.i) I will get..
    >
    > 1115947008
    >
    > and then printf("%f\n", S.f) I will get..
    >
    > 66.000000
    >
    > I read S.i first, after assigning to S.f. Assuming float and int
    > are both 32 bits, what about the foregoing is undefined behavior?
    > What can possibly be wrong with it?


    The 'wrong' thing is some idiot assuming that the access to S.f
    magically reorganizes the bits in S to form the integer 66. There
    are more and more of these idiots around, who have no idea what
    really goes on, and who depend on the use of 'SHAZAM'.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Apr 9, 2009
    #10
  11. On Wed, 08 Apr 2009 18:26:39 -0400, Joe Wright
    <> wrote:

    > wrote:
    >> jameskuyper <> wrote:
    >>> Any attempt to use the value of S.f2 or s.i at this point in the
    >>> program has undefined behavior. The only member of a union that you
    >>> can safely read is the member that was last written to.

    >>
    >> That was the rule in C90, but the rules in C99 recognize what really
    >> happens -- the existing bits are reinterpreted in the other type. Since
    >> f2 has the same type as the member that was last written to, the
    >> behavior of accessing it is completely defined. Accessing i is a bit
    >> more fluid; since the types are different, the existing bits may or may
    >> not be a valid representation. If they are, the behavior is well
    >> defined but the resulting value is unspecified. If not, all bets are
    >> off and you still get undefined behavior.

    >
    >I still don't get it.
    >
    > union s {
    > float f;
    > int i;
    > };
    >
    > union s S;
    > S.f = 66;
    >
    >The union S is essentially a 32-bit object with two names. The above
    >assignment will set the bits of S like this..
    >
    >01000010 10000100 00000000 00000000


    On my system the bits will be
    01000010 01100110 00000000 00000000
    My system uses hex floating point, not binary, so the leading bit in a
    normalized mantissa need not be 1.

    >
    >If I then printf("%d\n", S.i) I will get..
    >
    >1115947008


    You appear to have a big endian system. What abut the poor people
    with little endian ones? Will they see 33860?

    I would probably get 1113980928 but that still doesn't alter the fact
    that the behavior is undefined.

    >
    >and then printf("%f\n", S.f) I will get..
    >
    >66.000000
    >
    >I read S.i first, after assigning to S.f. Assuming float and int are
    >both 32 bits, what about the foregoing is undefined behavior? What can
    >possibly be wrong with it?


    The fact that the C90 standard says it is undefined. The compiler is
    not even obligated to generate the "expected" code, even though almost
    all do.

    It is not much different than passing overlapping fields to strcpy or
    memcpy. On most systems it will do the "expected." It is still
    undefined.

    --
    Remove del for email
    Barry Schwarz, Apr 9, 2009
    #11
  12. Tagore

    Guest

    On 9 Apr, 01:20, CBFalconer <> wrote:
    > Joe Wright wrote:


    > > I still don't get it.


    [stuff to do with unions]


    > >    union s {
    > >      float f;
    > >      int i;
    > >    };

    >
    > >    union s S;
    > >    S.f = 66;

    >
    > > The union S is essentially a 32-bit object with two names. The
    > > above assignment will set the bits of S like this..

    >
    > > 01000010 10000100 00000000 00000000

    >
    > > If I then printf("%d\n", S.i) I will get..

    >
    > > 1115947008

    >
    > > and then printf("%f\n", S.f) I will get..

    >
    > > 66.000000

    >
    > > I read S.i first, after assigning to S.f. Assuming float and int
    > > are both 32 bits, what about the foregoing is undefined behavior?


    the representations of int and float are different.
    and assuming both are 32-bits is a big assumption.

    > > What can possibly be wrong with it?


    Signalling NaN


    > The 'wrong' thing is some idiot assuming that the access to S.f
    > magically reorganizes the bits in S to form the integer 66.  There
    > are more and more of these idiots around, who have no idea what
    > really goes on, and who depend on the use of 'SHAZAM'.


    A bit unfair, I think. Floating point has some non-intuitive
    properties
    and with unions you are getting pretty chummy with the hardware.

    At least this guy is asking the questions.
    , Apr 9, 2009
    #12
  13. writes:
    > On 9 Apr, 01:20, CBFalconer <> wrote:
    >> Joe Wright wrote:

    [...]
    >> >    union s {
    >> >      float f;
    >> >      int i;
    >> >    };

    >>
    >> >    union s S;
    >> >    S.f = 66;

    [...]
    >> > What can possibly be wrong with it?

    >
    > Signalling NaN

    [...]

    Signalling NaNs aren't an issue in this particular case. The value 66
    (converted to 66.0f) was stored in S.f. The problem is that S.i could
    contain a trap representation, either because the bit pattern used to
    represent 66.0f happens to be a trap representation for type int, or
    because int is bigger than float and the remaining bits of S.i are
    garbage.

    (In practice, most implementations don't have trap representations for
    type int, but you can't assume that in portable code.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Apr 9, 2009
    #13
  14. Tagore

    James Kuyper Guest

    CBFalconer wrote:
    > Joe Wright wrote:
    > ... snip ...
    >> I still don't get it.
    >>
    >> union s {
    >> float f;
    >> int i;
    >> };
    >>
    >> union s S;
    >> S.f = 66;
    >>
    >> The union S is essentially a 32-bit object with two names. The
    >> above assignment will set the bits of S like this..
    >>
    >> 01000010 10000100 00000000 00000000
    >>
    >> If I then printf("%d\n", S.i) I will get..
    >>
    >> 1115947008
    >>
    >> and then printf("%f\n", S.f) I will get..
    >>
    >> 66.000000
    >>
    >> I read S.i first, after assigning to S.f. Assuming float and int
    >> are both 32 bits, what about the foregoing is undefined behavior?
    >> What can possibly be wrong with it?

    >
    > The 'wrong' thing is some idiot assuming that the access to S.f
    > magically reorganizes the bits in S to form the integer 66. There


    He's said nothing to suggest that he's expecting a magical
    reorganization. In one of the earlier messages which are invisible to
    you, he has very explicitly stated that he expects the member with the
    type that is different from the one most recently written to have a
    "garbage" value, by which he apparently means a value which has a
    relationship to the value written that can only be predicted by a
    complicated process that depends upon the precise details of how both
    'int' and 'float' are represented, and as such is highly non-portable.

    What he didn't understand was how the consequences could be anything
    worse than a garbage value. He was apparently unfamiliar with the
    possibility of trap representations, and couldn't imagine any of the
    more exotic ways in which the code could fail.
    James Kuyper, Apr 9, 2009
    #14
  15. Tagore

    Guest

    jameskuyper <> wrote:
    >
    > Even on platforms without such exotic hardware, the fact that the
    > standard says that this has undefined behavior indirectly opens up
    > other possible failure modes. For instance, it gives implementations
    > permission to perform optimizations that would otherwise be illegal.


    Not in C99.
    --
    Larry Jones

    My "C-" firmly establishes me on the cutting edge of the avant-garde.
    -- Calvin
    , Apr 9, 2009
    #15
  16. Tagore

    jameskuyper Guest

    wrote:
    > jameskuyper <> wrote:
    > >
    > > Even on platforms without such exotic hardware, the fact that the
    > > standard says that this has undefined behavior indirectly opens up
    > > other possible failure modes. For instance, it gives implementations
    > > permission to perform optimizations that would otherwise be illegal.

    >
    > Not in C99.


    Sorry - I should have clarified that I was referring to C90. You've
    already pointed out that distinction, and I failed to acknowledge it.
    jameskuyper, Apr 9, 2009
    #16
  17. Tagore

    CBFalconer Guest

    wrote:
    > CBFalconer <> wrote:
    >> Joe Wright wrote:
    >>

    > [stuff to do with unions]
    >
    >>> union s {
    >>> float f;
    >>> int i;
    >>> };
    >>>
    >>> union s S;
    >>> S.f = 66;
    >>>
    >>> The union S is essentially a 32-bit object with two names. The
    >>> above assignment will set the bits of S like this..
    >>>
    >>> 01000010 10000100 00000000 00000000
    >>>
    >>> If I then printf("%d\n", S.i) I will get..
    >>>
    >>> 1115947008
    >>>
    >>> and then printf("%f\n", S.f) I will get..
    >>>
    >>> 66.000000
    >>>
    >>> I read S.i first, after assigning to S.f. Assuming float and int
    >>> are both 32 bits, what about the foregoing is undefined behavior?

    >

    .... snip ...
    >
    >> The 'wrong' thing is some idiot assuming that the access to S.f
    >> magically reorganizes the bits in S to form the integer 66. There
    >> are more and more of these idiots around, who have no idea what
    >> really goes on, and who depend on the use of 'SHAZAM'.

    >
    > A bit unfair, I think. Floating point has some non-intuitive
    > properties and with unions you are getting pretty chummy with the
    > hardware. At least this guy is asking the questions.


    You have a point. However, to me, the fact that two items occupy
    the same space and can represent different sets of values screams
    that "the format is different".

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Apr 9, 2009
    #17
  18. Tagore

    James Kuyper Guest

    CBFalconer wrote:
    > wrote:
    >> CBFalconer <> wrote:
    >>> Joe Wright wrote:
    >>>

    >> [stuff to do with unions]
    >>
    >>>> union s {
    >>>> float f;
    >>>> int i;
    >>>> };
    >>>>
    >>>> union s S;
    >>>> S.f = 66;
    >>>>
    >>>> The union S is essentially a 32-bit object with two names. The
    >>>> above assignment will set the bits of S like this..
    >>>>
    >>>> 01000010 10000100 00000000 00000000
    >>>>
    >>>> If I then printf("%d\n", S.i) I will get..
    >>>>
    >>>> 1115947008
    >>>>
    >>>> and then printf("%f\n", S.f) I will get..
    >>>>
    >>>> 66.000000
    >>>>
    >>>> I read S.i first, after assigning to S.f. Assuming float and int
    >>>> are both 32 bits, what about the foregoing is undefined behavior?

    > ... snip ...
    >>> The 'wrong' thing is some idiot assuming that the access to S.f
    >>> magically reorganizes the bits in S to form the integer 66. There
    >>> are more and more of these idiots around, who have no idea what
    >>> really goes on, and who depend on the use of 'SHAZAM'.

    >> A bit unfair, I think. Floating point has some non-intuitive
    >> properties and with unions you are getting pretty chummy with the
    >> hardware. At least this guy is asking the questions.

    >
    > You have a point. However, to me, the fact that two items occupy
    > the same space and can represent different sets of values screams
    > that "the format is different".


    Yes, but he said nothing to suggest that he was unaware of that fact. He
    in no way implied that he expected anything like the magical
    reorganization you refer to. He just expected that the bits that were
    written as a floating point value would be reinterpreted as a
    representing a very different integer value, with no unexpected side
    effects.
    James Kuyper, Apr 10, 2009
    #18
  19. Tagore

    CBFalconer Guest

    James Kuyper wrote:
    > CBFalconer wrote:
    >> wrote:
    >>> CBFalconer <> wrote:
    >>>> Joe Wright wrote:
    >>>>
    >>> [stuff to do with unions]
    >>>
    >>>>> union s {
    >>>>> float f;
    >>>>> int i;
    >>>>> };
    >>>>>
    >>>>> union s S;
    >>>>> S.f = 66;
    >>>>>
    >>>>> The union S is essentially a 32-bit object with two names. The
    >>>>> above assignment will set the bits of S like this..
    >>>>>
    >>>>> 01000010 10000100 00000000 00000000
    >>>>>
    >>>>> If I then printf("%d\n", S.i) I will get..
    >>>>>
    >>>>> 1115947008
    >>>>>
    >>>>> and then printf("%f\n", S.f) I will get..
    >>>>>
    >>>>> 66.000000
    >>>>>
    >>>>> I read S.i first, after assigning to S.f. Assuming float and int
    >>>>> are both 32 bits, what about the foregoing is undefined behavior?

    >>
    >> ... snip ...
    >>
    >>>> The 'wrong' thing is some idiot assuming that the access to S.f
    >>>> magically reorganizes the bits in S to form the integer 66.
    >>>> There are more and more of these idiots around, who have no
    >>>> idea what really goes on, and who depend on the use of 'SHAZAM'.
    >>>
    >>> A bit unfair, I think. Floating point has some non-intuitive
    >>> properties and with unions you are getting pretty chummy with
    >>> the hardware. At least this guy is asking the questions.

    >>
    >> You have a point. However, to me, the fact that two items occupy
    >> the same space and can represent different sets of values screams
    >> that "the format is different".

    >
    > Yes, but he said nothing to suggest that he was unaware of that
    > fact. He in no way implied that he expected anything like the
    > magical reorganization you refer to. He just expected that the
    > bits that were written as a floating point value would be
    > reinterpreted as a representing a very different integer value,
    > with no unexpected side effects.


    Any such would require storage of the actual stored format, and the
    requested format. This can be an unlimited number of
    possibilities. Very minor thinking can infer the magic
    requirement, IMO. Since all objects are typed, casts provide that
    sort of information.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
    CBFalconer, Apr 11, 2009
    #19
  20. Tagore

    James Kuyper Guest

    CBFalconer wrote:
    > James Kuyper wrote:
    >> CBFalconer wrote:
    >>> wrote:
    >>>> CBFalconer <> wrote:
    >>>>> Joe Wright wrote:
    >>>>>
    >>>> [stuff to do with unions]
    >>>>
    >>>>>> union s {
    >>>>>> float f;
    >>>>>> int i;
    >>>>>> };
    >>>>>>
    >>>>>> union s S;
    >>>>>> S.f = 66;
    >>>>>>
    >>>>>> The union S is essentially a 32-bit object with two names. The
    >>>>>> above assignment will set the bits of S like this..
    >>>>>>
    >>>>>> 01000010 10000100 00000000 00000000
    >>>>>>
    >>>>>> If I then printf("%d\n", S.i) I will get..
    >>>>>>
    >>>>>> 1115947008
    >>>>>>
    >>>>>> and then printf("%f\n", S.f) I will get..
    >>>>>>
    >>>>>> 66.000000
    >>>>>>
    >>>>>> I read S.i first, after assigning to S.f. Assuming float and int
    >>>>>> are both 32 bits, what about the foregoing is undefined behavior?
    >>> ... snip ...
    >>>
    >>>>> The 'wrong' thing is some idiot assuming that the access to S.f
    >>>>> magically reorganizes the bits in S to form the integer 66.
    >>>>> There are more and more of these idiots around, who have no
    >>>>> idea what really goes on, and who depend on the use of 'SHAZAM'.
    >>>> A bit unfair, I think. Floating point has some non-intuitive
    >>>> properties and with unions you are getting pretty chummy with
    >>>> the hardware. At least this guy is asking the questions.
    >>> You have a point. However, to me, the fact that two items occupy
    >>> the same space and can represent different sets of values screams
    >>> that "the format is different".

    >> Yes, but he said nothing to suggest that he was unaware of that
    >> fact. He in no way implied that he expected anything like the
    >> magical reorganization you refer to. He just expected that the
    >> bits that were written as a floating point value would be
    >> reinterpreted as a representing a very different integer value,
    >> with no unexpected side effects.

    >
    > Any such would require storage of the actual stored format, and the
    > requested format.


    As the result depends only upon the bits that were stored, and not upon
    the format that was used to store them, why would you need to store that
    format?

    The requested format is determined by the union member used to refer to
    the object, there is no need to store this information anywhere, except
    in the sense that the sequence of instructions in the executable program
    that perform the retrieval can be considered as storing information
    about which format that is.

    > ... This can be an unlimited number of
    > possibilities. ...


    No, in a union with two members, there's only two possibilities; only
    the one that corresponds to the member you are currently referring to
    actually matters at any given point.

    > ... Very minor thinking can infer the magic
    > requirement, IMO.


    What's magical about writing the contents of a floating point register
    to RAM, then reading the contents of that ram into an integer register?
    I get the impression that you are still of the mistaken opinion that he
    expressed an expectation that the integer he retrieved would have the
    same numerical values as the floating point number he stored. He
    expressed no such expectation.

    > ... Since all objects are typed, ...


    That is not true. Dynamically allocated memory constitutes an object
    that has no declared type, and no effective type. It can acquire an
    effective type by being written to using an lvalue that is not of
    character type, or by a memcpy() from another object that does have an
    effective type. But until that happens, that object does not have a type
    (6.5p6).
    James Kuyper, Apr 11, 2009
    #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. Matt Garman
    Replies:
    1
    Views:
    664
    Matt Garman
    Apr 25, 2004
  2. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    869
    Chris Torek
    Apr 26, 2004
  3. Ian Roddis

    xslt queries in xml to SQL queries

    Ian Roddis, Feb 26, 2006, in forum: Python
    Replies:
    3
    Views:
    1,496
    Crutcher
    Feb 26, 2006
  4. Abby Lee

    so many queries within queries I'm confused

    Abby Lee, Aug 4, 2004, in forum: ASP General
    Replies:
    11
    Views:
    351
    Aaron [SQL Server MVP]
    Aug 6, 2004
  5. d2r2

    Nested MSAccess Union-Queries in asp

    d2r2, Dec 28, 2004, in forum: ASP General
    Replies:
    2
    Views:
    230
Loading...

Share This Page