double casts

Discussion in 'C Programming' started by Martijn, Nov 2, 2003.

  1. Martijn

    Martijn Guest

    Hi,

    Those familiar with Windows programming may be familiar with the windowsx.h
    header. In this header macros exist that use double casts, like so (hope
    this is readable):

    #define ComboBox_LimitText(hwndCtl,cchLimit) \

    ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))

    Why is this? Does this help in typechecking? (I would think not).

    Thanks for the info,

    --
    Martijn
    http://www.sereneconcepts.nl
     
    Martijn, Nov 2, 2003
    #1
    1. Advertising

  2. Martijn

    Jack Klein Guest

    On Sun, 2 Nov 2003 13:33:05 +0100, "Martijn"
    <> wrote in comp.lang.c:

    > Hi,
    >
    > Those familiar with Windows programming may be familiar with the windowsx.h
    > header. In this header macros exist that use double casts, like so (hope
    > this is readable):


    Your text is readable, the concept of what the code is doing is not.

    > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    >
    > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    >
    > Why is this? Does this help in typechecking? (I would think not).


    Casts never help in type checking, they specifically exist to defeat
    type checking.

    > Thanks for the info,


    For a variety of reasons, Windows header files are a complete and
    total mess. If you really want to delve into the details, I'd suggest
    a Windows programming group or one of Microsoft's support groups.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c /faq
     
    Jack Klein, Nov 2, 2003
    #2
    1. Advertising

  3. Martijn

    xarax Guest

    "Jack Klein" <> wrote in message
    news:eek:...
    > On Sun, 2 Nov 2003 13:33:05 +0100, "Martijn"
    > <> wrote in comp.lang.c:
    >
    > > Hi,
    > >
    > > Those familiar with Windows programming may be familiar with the windowsx.h
    > > header. In this header macros exist that use double casts, like so (hope
    > > this is readable):

    >
    > Your text is readable, the concept of what the code is doing is not.
    >
    > > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    > >
    > > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    > >
    > > Why is this? Does this help in typechecking? (I would think not).

    >
    > Casts never help in type checking, they specifically exist to defeat
    > type checking.
    >
    > > Thanks for the info,

    >
    > For a variety of reasons, Windows header files are a complete and
    > total mess. If you really want to delve into the details, I'd suggest
    > a Windows programming group or one of Microsoft's support groups.


    That wasn't his question.

    His question is this: When is it necessary, if ever, to use
    a double cast?

    For example:

    1. (WPARM)(int)(cchLimit)

    2. (WPARM)(cchLimit)

    Are these two expressions *always* equivalent? Is there ever
    a situation where the intermediate cast (int) is necessary
    to get a "correct" final cast to (WPARM)?

    Just ignore whatever "WPARM" is supposed to be and think
    about the generic question of double casting versus single casting.
    Don't get distracted about Windows. This is really a C question.

    For you C gurus out there, what is the definitive answer?
     
    xarax, Nov 2, 2003
    #3
  4. xarax <> scribbled the following:
    > "Jack Klein" <> wrote in message
    > news:eek:...
    >> On Sun, 2 Nov 2003 13:33:05 +0100, "Martijn"
    >> <> wrote in comp.lang.c:
    >> > Hi,
    >> >
    >> > Those familiar with Windows programming may be familiar with the windowsx.h
    >> > header. In this header macros exist that use double casts, like so (hope
    >> > this is readable):

    >>
    >> Your text is readable, the concept of what the code is doing is not.
    >>
    >> > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    >> >
    >> > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    >> >
    >> > Why is this? Does this help in typechecking? (I would think not).

    >>
    >> Casts never help in type checking, they specifically exist to defeat
    >> type checking.
    >>
    >> > Thanks for the info,

    >>
    >> For a variety of reasons, Windows header files are a complete and
    >> total mess. If you really want to delve into the details, I'd suggest
    >> a Windows programming group or one of Microsoft's support groups.


    > That wasn't his question.


    > His question is this: When is it necessary, if ever, to use
    > a double cast?


    > For example:


    > 1. (WPARM)(int)(cchLimit)


    > 2. (WPARM)(cchLimit)


    > Are these two expressions *always* equivalent? Is there ever
    > a situation where the intermediate cast (int) is necessary
    > to get a "correct" final cast to (WPARM)?


    > Just ignore whatever "WPARM" is supposed to be and think
    > about the generic question of double casting versus single casting.
    > Don't get distracted about Windows. This is really a C question.


    > For you C gurus out there, what is the definitive answer?


    I am not a C guru and cannot answer the OP's question, but I can say
    for certain that in general, an expression of the type (A)(B)something
    is not the same thing as (A)something.
    Proof:
    int i;
    int *p1 = (int *)&i;
    int *p2 = (int *)(long)&i;
    p1 is guaranteed to store i's address. p2 is not.

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "We're women. We've got double standards to live up to."
    - Ally McBeal
     
    Joona I Palaste, Nov 2, 2003
    #4
  5. Joona I Palaste <> writes:
    [...]
    > I am not a C guru and cannot answer the OP's question, but I can say
    > for certain that in general, an expression of the type (A)(B)something
    > is not the same thing as (A)something.
    > Proof:
    > int i;
    > int *p1 = (int *)&i;
    > int *p2 = (int *)(long)&i;
    > p1 is guaranteed to store i's address. p2 is not.


    Ok, that's a good example of when a double cast is harmful. Are there
    any cases where it's helpful -- i.e., where (A)(B)something differs
    from (A)something *and* (A)(B)something does something useful that
    (A)something does not. In other words, if I see (A)(B)something in
    source code, can I always delete the "(B)" without breaking anything?

    Here's one example (assume 8-bit char):

    unsigned int n = 257;
    float f0 = (float)n; /* f0 == 257.0 */
    float f1 = (float)(unsigned char)n; /* f1 == 1.0 */

    Are there any examples not involving deliberate loss of information?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
    Schroedinger does Shakespeare: "To be *and* not to be"
     
    Keith Thompson, Nov 2, 2003
    #5
  6. Martijn

    CBFalconer Guest

    xarax wrote:
    > "Jack Klein" <> wrote in message
    > > "Martijn" <> wrote:
    > > >
    > > > Those familiar with Windows programming may be familiar with
    > > > the windowsx.h header. In this header macros exist that use
    > > > double casts, like so (hope this is readable):
    > > >
    > > > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    > > >
    > > > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    > > >
    > > > Why is this? Does this help in typechecking? (I would think
    > > > not).

    > >
    > > Casts never help in type checking, they specifically exist to
    > > defeat type checking.
    > >
    > > For a variety of reasons, Windows header files are a complete
    > > and total mess. If you really want to delve into the details,
    > > I'd suggest a Windows programming group or one of Microsoft's
    > > support groups.

    >
    > That wasn't his question.
    >
    > His question is this: When is it necessary, if ever, to use
    > a double cast?
    >
    > For example:
    >
    > 1. (WPARM)(int)(cchLimit)
    > 2. (WPARM)(cchLimit)
    >
    > Are these two expressions *always* equivalent? Is there ever
    > a situation where the intermediate cast (int) is necessary
    > to get a "correct" final cast to (WPARM)?
    >
    > Just ignore whatever "WPARM" is supposed to be and think
    > about the generic question of double casting versus single
    > casting. Don't get distracted about Windows. This is really
    > a C question.
    >
    > For you C gurus out there, what is the definitive answer?


    One possibility that occurs to me is when you don't know the
    signedness of the original item. Thus you might need:

    (size_t) ((unsigned char) ch)

    which could avoid generating a large number from '\0xff', say.

    However the essential illegitimacy of windows headers remains :)

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Nov 2, 2003
    #6
  7. On Sun, 02 Nov 2003 20:45:22 +0000, Keith Thompson wrote:

    > Joona I Palaste <> writes:
    > [...]
    >> I am not a C guru and cannot answer the OP's question, but I can say
    >> for certain that in general, an expression of the type (A)(B)something
    >> is not the same thing as (A)something.
    >> Proof:
    >> int i;
    >> int *p1 = (int *)&i;
    >> int *p2 = (int *)(long)&i;
    >> p1 is guaranteed to store i's address. p2 is not.

    >
    > Ok, that's a good example of when a double cast is harmful. Are there
    > any cases where it's helpful -- i.e., where (A)(B)something differs
    > from (A)something *and* (A)(B)something does something useful that
    > (A)something does not. In other words, if I see (A)(B)something in
    > source code, can I always delete the "(B)" without breaking anything?
    >
    > Here's one example (assume 8-bit char):
    >
    > unsigned int n = 257;
    > float f0 = (float)n; /* f0 == 257.0 */
    > float f1 = (float)(unsigned char)n; /* f1 == 1.0 */
    >
    > Are there any examples not involving deliberate loss of information?


    I have some code that uses a few double casts, but they rely on
    implementation-defined behavior -- specifically that an unsigned
    integer cast to a signed integer becomes the signed integer value
    with the same bit value as the unsigned integer.

    i.e.:
    unsigned char uc = 255;
    signed char sc = (signed char)uc;
    /* sc has value -1 */

    The code does things like this:

    short s;
    unsigned char uca, ucb;
    ...
    ++uca; /* increment with intended wrap from 255 to 0 */
    ...
    --ucb; /* decrement with intended wrap from 0 to 255 */
    ...
    s = (short)(signed char)uca + (short)(signed char)ucb;

    The (signed char) casts are necessary to force the two
    values being added into the range -128..+127 and the (short)
    casts are necessary to prevent problems when the sum would
    overflow a signed char.
     
    Sheldon Simms, Nov 2, 2003
    #7
  8. Sheldon Simms <> wrote in message news:<>...
    ....
    > unsigned char uc = 255;
    > signed char sc = (signed char)uc;
    > /* sc has value -1 */


    There is no standard guarantee that sc has the value -1.

    If 255 <= SCHAR_MAX, then sc gets the value 255, otherwise 255 is
    converted in an implementation defined way. [C99 allows an
    implementation defined signal to be raised, although that's highly
    unlikely.]

    --
    Peter
     
    Peter Nilsson, Nov 3, 2003
    #8
  9. On Sun, 02 Nov 2003 18:05:24 -0800, Peter Nilsson wrote:

    > Sheldon Simms <> wrote in message news:<>...
    > ...
    >> unsigned char uc = 255;
    >> signed char sc = (signed char)uc;
    >> /* sc has value -1 */

    >
    > There is no standard guarantee that sc has the value -1.
    >
    > If 255 <= SCHAR_MAX, then sc gets the value 255, otherwise 255 is
    > converted in an implementation defined way. [C99 allows an
    > implementation defined signal to be raised, although that's highly
    > unlikely.]


    Thanks for pointing that out, even though I had already said that
    my code relied on implementation defined behavior. Since you didn't
    bother quoting it, here's what I said:

    >> I have some code that uses a few double casts, but they rely on
    >> implementation-defined behavior


    -Sheldon
     
    Sheldon Simms, Nov 3, 2003
    #9
  10. "Sheldon Simms" <> wrote in message
    news:p...
    > On Sun, 02 Nov 2003 18:05:24 -0800, Peter Nilsson wrote:
    > > Sheldon Simms <> wrote in message

    news:<>...
    > > ...
    > >> unsigned char uc = 255;
    > >> signed char sc = (signed char)uc;
    > >> /* sc has value -1 */

    > >
    > > There is no standard guarantee that sc has the value -1.
    > >
    > > If 255 <= SCHAR_MAX, then sc gets the value 255, otherwise 255 is
    > > converted in an implementation defined way. [C99 allows an
    > > implementation defined signal to be raised, although that's highly
    > > unlikely.]

    >
    > Thanks for pointing that out, even though I had already said that
    > my code relied on implementation defined behavior.
    >
    > Since you didn't bother quoting it, here's what I said:


    It's not that I didn't bother; I wanted to isolate the specific code that my
    comment referred to.

    > >> I have some code that uses a few double casts, but they rely on
    > >> implementation-defined behavior


    Continued by...

    > >> --specifically that an unsigned
    > >> integer cast to a signed integer becomes the signed integer value
    > >> with the same bit value as the unsigned integer.


    Which isn't actually enough to give sc the value -1, even on an 8 bit char
    implementation. You need the further assumption of two's complement.

    Even implementation specific code is worth analysing from the point of view
    of trying to make it (and similar code) non implementation dependant. To do
    that, we (or at least I) need to discus what those dependancies are, i.e.
    what the standards guarantee, and what they don't. For me, that is the whole
    point of comp.lang.c.

    In any case, I apologise if you feel I misrepresented you by taking your
    post too far out of context.

    --
    Peter
     
    Peter Nilsson, Nov 3, 2003
    #10
  11. On Mon, 03 Nov 2003 23:56:49 +1100, Peter Nilsson wrote:

    > "Sheldon Simms" <> wrote in message
    > news:p...
    >> On Sun, 02 Nov 2003 18:05:24 -0800, Peter Nilsson wrote:
    >> > Sheldon Simms <> wrote in message

    > news:<>...
    >> > ...
    >> >> unsigned char uc = 255;
    >> >> signed char sc = (signed char)uc;
    >> >> /* sc has value -1 */
    >> >
    >> > There is no standard guarantee that sc has the value -1.
    >> >
    >> > If 255 <= SCHAR_MAX, then sc gets the value 255, otherwise 255 is
    >> > converted in an implementation defined way. [C99 allows an
    >> > implementation defined signal to be raised, although that's highly
    >> > unlikely.]

    >>
    >> Thanks for pointing that out, even though I had already said that
    >> my code relied on implementation defined behavior.
    >>
    >> Since you didn't bother quoting it, here's what I said:

    >
    > It's not that I didn't bother; I wanted to isolate the specific code that my
    > comment referred to.
    >
    >> >> I have some code that uses a few double casts, but they rely on
    >> >> implementation-defined behavior

    >
    > Continued by...
    >
    >> >> --specifically that an unsigned
    >> >> integer cast to a signed integer becomes the signed integer value
    >> >> with the same bit value as the unsigned integer.

    >
    > Which isn't actually enough to give sc the value -1, even on an 8 bit char
    > implementation. You need the further assumption of two's complement.


    True. I realized after posting that this sentence didn't completely
    describe the kind of implementation-defined behavior I was relying on.
     
    Sheldon Simms, Nov 3, 2003
    #11
  12. Martijn

    Dan Pop Guest

    In <> Keith Thompson <> writes:

    >Ok, that's a good example of when a double cast is harmful. Are there
    >any cases where it's helpful -- i.e., where (A)(B)something differs
    >from (A)something *and* (A)(B)something does something useful that
    >(A)something does not. In other words, if I see (A)(B)something in
    >source code, can I always delete the "(B)" without breaking anything?
    >
    >Here's one example (assume 8-bit char):
    >
    > unsigned int n = 257;
    > float f0 = (float)n; /* f0 == 257.0 */
    > float f1 = (float)(unsigned char)n; /* f1 == 1.0 */
    >
    >Are there any examples not involving deliberate loss of information?


    Sure:

    int n = -1;
    double f0 = (double)n; /* f0 == -1.0 */
    double f1 = (double)(unsigned)n; /* f1 == (double)UINT_MAX */

    No information is lost. The value of n can be retrieved from the value
    of f1. That is, assuming that a double's mantissa has more bits than an
    unsigned.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 3, 2003
    #12
  13. Martijn

    Martijn Guest

    > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    >
    >

    ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    >
    > Why is this? Does this help in typechecking? (I would think not).
    >
    > Thanks for the info,


    Thanks for everybody who gave this a thought. I guess I'll post it on one
    of the MS group, see if any ex-microsoftie has anything to say about it :)

    --
    Martijn
    http://www.sereneconcepts.nl
     
    Martijn, Nov 4, 2003
    #13
  14. Joona I Palaste <> wrote in message news:<bo3kf6$6v9$>...
    > xarax <> scribbled the following:
    > > "Jack Klein" <> wrote in message
    > > news:eek:...
    > >> On Sun, 2 Nov 2003 13:33:05 +0100, "Martijn"
    > >> <> wrote in comp.lang.c:
    > >> > Hi,
    > >> >
    > >> > Those familiar with Windows programming may be familiar with the windowsx.h
    > >> > header. In this header macros exist that use double casts, like so (hope
    > >> > this is readable):
    > >>
    > >> Your text is readable, the concept of what the code is doing is not.
    > >>
    > >> > #define ComboBox_LimitText(hwndCtl,cchLimit) \
    > >> >
    > >> > ((int)(DWORD)SendMessage((hwndCtl),CB_LIMITTEXT,(WPARAM)(int)(cchLimit),0))
    > >> >
    > >> > Why is this? Does this help in typechecking? (I would think not).
    > >>
    > >> Casts never help in type checking, they specifically exist to defeat
    > >> type checking.
    > >>
    > >> > Thanks for the info,
    > >>
    > >> For a variety of reasons, Windows header files are a complete and
    > >> total mess. If you really want to delve into the details, I'd suggest
    > >> a Windows programming group or one of Microsoft's support groups.

    >
    > > That wasn't his question.

    >
    > > His question is this: When is it necessary, if ever, to use
    > > a double cast?

    >
    > > For example:

    >
    > > 1. (WPARM)(int)(cchLimit)

    >
    > > 2. (WPARM)(cchLimit)

    >
    > > Are these two expressions *always* equivalent? Is there ever
    > > a situation where the intermediate cast (int) is necessary
    > > to get a "correct" final cast to (WPARM)?

    >
    > > Just ignore whatever "WPARM" is supposed to be and think
    > > about the generic question of double casting versus single casting.
    > > Don't get distracted about Windows. This is really a C question.

    >
    > > For you C gurus out there, what is the definitive answer?

    >
    > I am not a C guru and cannot answer the OP's question, but I can say
    > for certain that in general, an expression of the type (A)(B)something
    > is not the same thing as (A)something.
    > Proof:
    > int i;
    > int *p1 = (int *)&i;
    > int *p2 = (int *)(long)&i;
    > p1 is guaranteed to store i's address. p2 is not.


    why would the long mess this up? if i's address can be represented as
    long, then wouldn't that be perfectly okay?

    - nethlek
     
    Mantorok Redgormor, Nov 5, 2003
    #14
  15. Mantorok Redgormor <> scribbled the following:
    > Joona I Palaste <> wrote in message news:<bo3kf6$6v9$>...
    >> I am not a C guru and cannot answer the OP's question, but I can say
    >> for certain that in general, an expression of the type (A)(B)something
    >> is not the same thing as (A)something.
    >> Proof:
    >> int i;
    >> int *p1 = (int *)&i;
    >> int *p2 = (int *)(long)&i;
    >> p1 is guaranteed to store i's address. p2 is not.


    > why would the long mess this up? if i's address can be represented as
    > long, then wouldn't that be perfectly okay?


    IF i's address can be represented as long. That's a mighty big IF you
    got there.
    And even if that's true, there's no guarantee the host CPU returns
    scalars and pointers in the same way. It could use different registers,
    for instance, in which case p2 will be pure garbage.

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "'I' is the most beautiful word in the world."
    - John Nordberg
     
    Joona I Palaste, Nov 5, 2003
    #15
  16. Martijn

    Dan Pop Guest

    In <boalcr$eg7$> Joona I Palaste <> writes:

    >Mantorok Redgormor <> scribbled the following:
    >> Joona I Palaste <> wrote in message news:<bo3kf6$6v9$>...
    >>> I am not a C guru and cannot answer the OP's question, but I can say
    >>> for certain that in general, an expression of the type (A)(B)something
    >>> is not the same thing as (A)something.
    >>> Proof:
    >>> int i;
    >>> int *p1 = (int *)&i;
    >>> int *p2 = (int *)(long)&i;
    >>> p1 is guaranteed to store i's address. p2 is not.

    >
    >> why would the long mess this up? if i's address can be represented as
    >> long, then wouldn't that be perfectly okay?

    >
    >IF i's address can be represented as long. That's a mighty big IF you
    >got there.


    And even then, there is no guarantee that the conversion between pointers
    and integers (and vice versa) yields meaningful results. Only C99
    provides such a guarantee, *if* intptr_t and uintptr_t are defined (and
    used in the conversion) and if the pointers are void pointers. In such
    a case, the code would be:

    int *p2 = (void *)(intptr_t)(void *)&i;

    which is kinda silly, of course. A final cast to int * is not necessary.

    >And even if that's true, there's no guarantee the host CPU returns
    >scalars and pointers in the same way. It could use different registers,
    >for instance, in which case p2 will be pure garbage.


    Huh? I can see no function call in the code. What am I missing?

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 5, 2003
    #16
  17. Dan Pop <> scribbled the following:
    > In <boalcr$eg7$> Joona I Palaste <> writes:
    >>And even if that's true, there's no guarantee the host CPU returns
    >>scalars and pointers in the same way. It could use different registers,
    >>for instance, in which case p2 will be pure garbage.


    > Huh? I can see no function call in the code. What am I missing?


    You're missing the fact that I can sometimes fumble up in my
    terminology. By "return" I meant something like "store". Is a cast to
    an (int *) allowed to read from a different register than a cast to a
    (long)?

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "Ice cream sales somehow cause drownings: both happen in summer."
    - Antti Voipio & Arto Wikla
     
    Joona I Palaste, Nov 5, 2003
    #17
  18. Martijn

    Dan Pop Guest

    In <bob3ic$nb4$> Joona I Palaste <> writes:

    >Dan Pop <> scribbled the following:
    >> In <boalcr$eg7$> Joona I Palaste <> writes:
    >>>And even if that's true, there's no guarantee the host CPU returns
    >>>scalars and pointers in the same way. It could use different registers,
    >>>for instance, in which case p2 will be pure garbage.

    >
    >> Huh? I can see no function call in the code. What am I missing?

    >
    >You're missing the fact that I can sometimes fumble up in my
    >terminology. By "return" I meant something like "store". Is a cast to
    >an (int *) allowed to read from a different register than a cast to a
    >(long)?


    Now, you're severely confused: the evaluation of an expression is defined
    in terms of values, it is immaterial where these values are stored, as
    long as all of them are obtained via legit means. It is compiler's job
    to do the right thing and it has all the necessary information for that.

    Such things can happen only when misdeclared functions are involved.
    Consider the following *complete* program (on a C89 implementation):

    int main()
    {
    return sin(0.0);
    }

    In the absence of an explicit declaration, sin() is implicitly declared
    as returning int. Therefore, after generating the function call, the
    compiler will expect the return value to be in whatever place a function
    returning int will put its return value. But the sin() function doesn't
    "know" that and it will put its return value in whatever place a function
    returning double is supposed to put its return value. The final result
    being that return will use an indeterminate value (but undefined behaviour
    has already been invoked by the time sin() was called.

    Even worse things can happen if the stack is used for passing back the
    return value, because the caller generates a certain stack layout, while
    the callee expects another, possibly corrupting stack data containing the
    callers local variables or its return address.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Nov 5, 2003
    #18
  19. Dan Pop <> scribbled the following:
    > In <bob3ic$nb4$> Joona I Palaste <> writes:
    >>Dan Pop <> scribbled the following:
    >>> In <boalcr$eg7$> Joona I Palaste <> writes:
    >>>>And even if that's true, there's no guarantee the host CPU returns
    >>>>scalars and pointers in the same way. It could use different registers,
    >>>>for instance, in which case p2 will be pure garbage.

    >>
    >>> Huh? I can see no function call in the code. What am I missing?

    >>
    >>You're missing the fact that I can sometimes fumble up in my
    >>terminology. By "return" I meant something like "store". Is a cast to
    >>an (int *) allowed to read from a different register than a cast to a
    >>(long)?


    > Now, you're severely confused: the evaluation of an expression is defined
    > in terms of values, it is immaterial where these values are stored, as
    > long as all of them are obtained via legit means. It is compiler's job
    > to do the right thing and it has all the necessary information for that.


    > Such things can happen only when misdeclared functions are involved.
    > Consider the following *complete* program (on a C89 implementation):


    > int main()
    > {
    > return sin(0.0);
    > }


    > In the absence of an explicit declaration, sin() is implicitly declared
    > as returning int. Therefore, after generating the function call, the
    > compiler will expect the return value to be in whatever place a function
    > returning int will put its return value. But the sin() function doesn't
    > "know" that and it will put its return value in whatever place a function
    > returning double is supposed to put its return value. The final result
    > being that return will use an indeterminate value (but undefined behaviour
    > has already been invoked by the time sin() was called.


    Thanks, Dan! You deconfused me pretty well. So in other words, when
    evaluating the expressions, the compiler "knows" the correct types and
    the register mix-up I was talking about can't happen. But when the
    compiler is evaluating function calls, it doesn't necessarily "know" how
    the return values of the functions will be used.

    --
    /-- Joona Palaste () ------------- Finland --------\
    \-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
    "You can pick your friends, you can pick your nose, but you can't pick your
    relatives."
    - MAD Magazine
     
    Joona I Palaste, Nov 5, 2003
    #19
  20. On Wed, 5 Nov 2003, Joona I Palaste wrote:
    >
    > Dan Pop <> scribbled the following:
    > > Joona I Palaste <> writes:
    > >>And even if that's true, there's no guarantee the host CPU returns
    > >>scalars and pointers in the same way. It could use different registers,
    > >>for instance, in which case p2 will be pure garbage.

    >
    > > Huh? I can see no function call in the code. What am I missing?

    >
    > You're missing the fact that I can sometimes fumble up in my
    > terminology. By "return" I meant something like "store". Is a cast to
    > an (int *) allowed to read from a different register than a cast to a
    > (long)?


    (ITYM: Is an implementation allowed to make conversions between
    [non-intptr_t] integral and pointer types do funky, unpredictable
    stuff?)

    Technically, yes, as long as the implementation documents that
    behavior (N869 6.3.2.3#5). Of course, that would be a pretty silly
    implementation; it'd be much more user-friendly to simply convert all
    pointers to zero upon conversion to 'long'.

    And no, no *sensible* compiler would ever do such a thing. I
    don't think it would simplify anything if one made the compiler
    do that.

    -Arthur
     
    Arthur J. O'Dwyer, Nov 5, 2003
    #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. =?Utf-8?B?Q2hyaXMgRGF2b2xp?=

    Web casts in ASP.Net

    =?Utf-8?B?Q2hyaXMgRGF2b2xp?=, Oct 19, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    526
    clintonG
    Oct 19, 2005
  2. cgbusch
    Replies:
    2
    Views:
    348
    Sudsy
    Jul 8, 2003
  3. Joona I Palaste

    Needless casts?

    Joona I Palaste, Apr 24, 2004, in forum: Java
    Replies:
    15
    Views:
    714
    Icemerth
    Apr 25, 2004
  4. Dan Upton

    checking casts

    Dan Upton, Nov 29, 2005, in forum: Java
    Replies:
    4
    Views:
    760
    Chris Smith
    Dec 1, 2005
  5. Sydex
    Replies:
    12
    Views:
    6,646
    Victor Bazarov
    Feb 17, 2005
Loading...

Share This Page