What shall return "0.0 ? 1 : 0" ?

Discussion in 'C Programming' started by Xavier Roche, Jul 20, 2012.

  1. Xavier Roche

    Xavier Roche Guest

    Hi folks!

    Is there a C standard expert who can confirm what shall return
    0.0 ? 1 : 0

    With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result is.. 1.

    Is the result undefined by the standard, by chance ?


    Regards,
    Xavier Roche
    Xavier Roche, Jul 20, 2012
    #1
    1. Advertising

  2. Xavier Roche <> writes:

    > Hi folks!
    >
    > Is there a C standard expert who can confirm what shall return
    > 0.0 ? 1 : 0
    >
    > With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result
    > is.. 1.


    How odd.

    > Is the result undefined by the standard, by chance ?


    No, it's defined to be 0.

    It does not violate any constraint that I can see, and the meaning
    depends solely on whether 0.0 "compares equal to 0". I can't find any
    justification for 0.0 not comparing equal to 0.

    The phases "x compares equal to 0" and "x compares unequal to 0" are
    used a lot in the standard. I've always taken them to mean x == 0 and x
    != 0, but I don't think that's ever stated explicitly.

    --
    Ben.
    Ben Bacarisse, Jul 20, 2012
    #2
    1. Advertising

  3. Xavier Roche

    Noob Guest

    Xavier Roche wrote:

    > Is there a C standard expert who can confirm what shall return
    > 0.0 ? 1 : 0
    >
    > With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result is.. 1.
    >
    > Is the result undefined by the standard, by chance ?


    Lemme see...

    3.3.15 Conditional operator

    Syntax

    conditional-expression:
    logical-OR-expression
    logical-OR-expression ? expression : conditional-expression

    Constraints

    The first operand shall have scalar type.
    [...]

    Semantics

    The first operand is evaluated; there is a sequence point after
    its evaluation. The second operand is evaluated only if the first
    compares unequal to 0; the third operand is evaluated only if the
    first compares equal to 0; the value of the second or third operand
    (whichever is evaluated) is the result[41].

    [41] A conditional expression does not yield an lvalue.

    0.0 is a 'floating-constant' which is a kind of 'primary-expression'
    which is a kind of 'logical-OR-expression'.

    (Scalar type means integral or floating or pointer.)

    Since 0.0 (the floating constant) compares equal to 0 (the integral constant)
    (0.0 ? 1 : 0) has value 0, as far as I can tell.

    Regards.
    Noob, Jul 20, 2012
    #3
  4. Xavier Roche

    Xavier Roche Guest

    On 07/20/2012 03:58 PM, Noob wrote:
    > Since 0.0 (the floating constant) compares equal to 0 (the integral constant)
    > (0.0 ? 1 : 0) has value 0, as far as I can tell.


    Thanks a lot to both of you. It appears to be a bug in Visual C++ 2010
    (*) then.

    This impression is confirmed when trying:
    static double zero = 0.0;
    ...
    zero ? 0 : 1
    which returns the correct value (0).

    (*) tested version: cl.exe 16.00.30319.01 for x64 (same issue using the
    x86 release)
    Xavier Roche, Jul 20, 2012
    #4
  5. Xavier Roche

    Noob Guest

    Xavier Roche wrote:
    > On 07/20/2012 03:58 PM, Noob wrote:
    >> Since 0.0 (the floating constant) compares equal to 0 (the integral constant)
    >> (0.0 ? 1 : 0) has value 0, as far as I can tell.

    >
    > Thanks a lot to both of you. It appears to be a bug in Visual C++ 2010
    > (*) then.
    >
    > This impression is confirmed when trying:
    > static double zero = 0.0;
    > ..
    > zero ? 0 : 1
    > which returns the correct value (0).


    NB: You swapped 0 and 1 there.

    ( 0.0 ? 42 : 666) evaluates to 666
    (zero ? 42 : 666) evaluates to 666
    Noob, Jul 20, 2012
    #5
  6. Xavier Roche

    Xavier Roche Guest

    On 07/20/2012 04:22 PM, Noob wrote:
    > NB: You swapped 0 and 1 there.


    Yes, my mistake (but the tested code is the initial one and has the
    wrong value)

    I have reported the issue on the "Visual C++ Language" forums (I can't
    understand why they ditched the microsoft.* groups for this piece of
    webforum junk by the way)
    Xavier Roche, Jul 20, 2012
    #6
  7. Xavier Roche

    Stefan Ram Guest

    Xavier Roche <> writes:
    >Is there a C standard expert who can confirm what shall return
    >0.0 ? 1 : 0


    An expression does not return. A function may return. After

    int f(){ return 0.0 ? 1 : 0; {

    , we can say that f »shall return 0.0 ? 1 : 0«.
    Stefan Ram, Jul 20, 2012
    #7
  8. Xavier Roche

    jacob navia Guest

    Le 20/07/12 15:21, Xavier Roche a écrit :
    > Hi folks!
    >
    > Is there a C standard expert who can confirm what shall return
    > 0.0 ? 1 : 0
    >
    > With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result
    > is.. 1.
    >
    > Is the result undefined by the standard, by chance ?
    >
    >
    > Regards,
    > Xavier Roche


    The bug is at the level of the compile-time interpretation since the
    result is not calculated at run time (even without aptimizations!)

    cl -FA bug.c yields this code:

    ; Listing generated by Microsoft (R) Optimizing Compiler Version
    16.00.30319.01

    include listing.inc

    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES

    _DATA SEGMENT
    $SG2584 DB '???', 00H
    ORG $+4
    $SG2585 DB '0.0 ? ??? : OK = %s', 0aH, 00H
    _DATA ENDS
    PUBLIC main
    EXTRN printf:pROC
    pdata SEGMENT
    $pdata$main DD imagerel $LN3
    DD imagerel $LN3+30
    DD imagerel $unwind$main
    pdata ENDS
    xdata SEGMENT
    $unwind$main DD 010401H
    DD 04204H
    ; Function compile flags: /Odtp
    xdata ENDS
    _TEXT SEGMENT
    main PROC
    ; File d:\lcc\bug.c
    ; Line 3
    $LN3:
    sub rsp, 40 ; 00000028H
    ; Line 4
    lea rdx, OFFSET FLAT:$SG2584
    lea rcx, OFFSET FLAT:$SG2585
    call printf
    ; Line 5
    xor eax, eax
    add rsp, 40 ; 00000028H
    ret 0
    main ENDP
    _TEXT ENDS
    END
    jacob navia, Jul 20, 2012
    #8
  9. -berlin.de (Stefan Ram) writes:
    > Xavier Roche <> writes:
    >>Is there a C standard expert who can confirm what shall return
    >>0.0 ? 1 : 0

    >
    > An expression does not return. A function may return. After
    >
    > int f(){ return 0.0 ? 1 : 0; {
    >
    > , we can say that f »shall return 0.0 ? 1 : 0«.


    An expression *yields* a value. (I think earlier versions of the
    standard used the word "return" for the results of expressions in
    some places; as far as I know it's been cleaned up.)

    I agree that it's not strictly correct to say that an expression
    returns a value, but the intended meaning is clear enough.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jul 20, 2012
    #9
  10. Xavier Roche

    Stefan Ram Guest

    expressions, evaluations, and values (was: What shall return "0.0 ? 1 : 0" ?)

    Keith Thompson <> writes:
    >An expression *yields* a value. (I think earlier versions of the
    >standard used the word "return" for the results of expressions in
    >some places; as far as I know it's been cleaned up.)


    I'd say that an expression /had/ a value (and that an /evaluation/
    yielded a value). Let me try to find quotations in N1570:

    »Its lifetime begins when the expression is evaluated
    and its initial value is the value of the expression.«
    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    »An actual implementation need not evaluate part of an
    expression if it can deduce that its value is not used
    and that no needed side effects are produced«

    »the value of CHAR_MIN«

    »expressions with implementation-defined values«

    »Its lifetime begins when the expression is evaluated
    and its initial value is the value of the expression.«

    »If an expression of any other type is evaluated as a
    void expression, its value or designator is discarded.«

    The relationship between an expression and its value in all
    these quotes (selected without bias) is always /possessive/,
    hence /has/.

    However, I'd like to add that for run-time values, it would
    be more correct never to say that /an expression had/ a value,
    since the value is in a one-to-one correspondence only with
    a single /evaluation/, because each evaluation of an
    expression may yield a different value. But it might be too
    cumbersome to always write »the value of an evaluation of x«
    instead of »the value of x«.
    Stefan Ram, Jul 20, 2012
    #10
  11. Xavier Roche <> writes:
    > Is there a C standard expert who can confirm what shall return
    > 0.0 ? 1 : 0
    >
    > With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result is.. 1.
    >
    > Is the result undefined by the standard, by chance ?


    As other responses have said, the result is well defined, and this
    appears to be a bug in Visual C++ 2010.

    I just tried this program:

    #include <stdio.h>
    int main(void) {
    printf("%d\n", 0.0 ? 1 : 0);
    if (0.0) {
    puts("0.0 is true");
    }
    else {
    puts("0.0 is false");
    }
    if (0.0 == 0) {
    puts("0.0 compares equal to 0");
    }
    else {
    puts("0.0 does not compare equal to 0");
    }
    return 0;
    }

    With gcc, the output is:

    0
    0.0 is false
    0.0 compares equal to 0

    With Visual Studio, the output is:

    1
    0.0 is false
    0.0 compares equal to 0

    with the language set to C and extensions disabled.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jul 20, 2012
    #11
  12. pete <> writes:
    > Keith Thompson wrote:
    >> -berlin.de (Stefan Ram) writes:
    >> > Xavier Roche <> writes:
    >> >>Is there a C standard expert who can confirm what shall return
    >> >>0.0 ? 1 : 0
    >> >
    >> > An expression does not return. A function may return. After
    >> >
    >> > int f(){ return 0.0 ? 1 : 0; {
    >> >
    >> > , we can say that f »shall return 0.0 ? 1 : 0«.

    >>
    >> An expression *yields* a value. (I think earlier versions of the
    >> standard used the word "return" for the results of expressions in
    >> some places; as far as I know it's been cleaned up.)

    >
    > Section "6.5 Expressions" in both C89 and in C99,
    > described the bitwise operators as returning values.


    C99 says they "return" values; N1256 says they "yield" values,
    as does N1570 (the C11 pre-release draft).

    None of the three Technical Corrigenda (which in theory constitute
    the difference between C99 and N1256) contain the word "yield".
    I think the editor, Larry Jones, just made the change himself.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jul 21, 2012
    #12
  13. Xavier Roche

    Phil Carmody Guest

    Keith Thompson <> writes:
    > pete <> writes:
    > > Keith Thompson wrote:
    > >> -berlin.de (Stefan Ram) writes:
    > >> > Xavier Roche <> writes:
    > >> >>Is there a C standard expert who can confirm what shall return
    > >> >>0.0 ? 1 : 0
    > >> >
    > >> > An expression does not return. A function may return. After
    > >> >
    > >> > int f(){ return 0.0 ? 1 : 0; {
    > >> >
    > >> > , we can say that f »shall return 0.0 ? 1 : 0«.
    > >>
    > >> An expression *yields* a value. (I think earlier versions of the
    > >> standard used the word "return" for the results of expressions in
    > >> some places; as far as I know it's been cleaned up.)

    > >
    > > Section "6.5 Expressions" in both C89 and in C99,
    > > described the bitwise operators as returning values.

    >
    > C99 says they "return" values; N1256 says they "yield" values,
    > as does N1570 (the C11 pre-release draft).
    >
    > None of the three Technical Corrigenda (which in theory constitute
    > the difference between C99 and N1256) contain the word "yield".
    > I think the editor, Larry Jones, just made the change himself.


    Not just that, but he disclosed that here after a discussion
    almost identical to this one. IIRC.

    Whilst I think it's good to wean people off inappropriate use of
    "return", I don't think it's worth making too big a thing of, at
    least if the question has been understood by everyone who didn't
    deliberately want to be adversarial.

    Phil
    --
    > I'd argue that there is much evidence for the existence of a God.

    Pics or it didn't happen.
    -- Tom (/. uid 822)
    Phil Carmody, Jul 21, 2012
    #13
  14. Xavier Roche

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > Xavier Roche <> writes:
    >
    >> Hi folks!
    >>
    >> Is there a C standard expert who can confirm what shall return
    >> 0.0 ? 1 : 0
    >>
    >> With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result
    >> is.. 1.

    >
    > How odd.
    >
    >> Is the result undefined by the standard, by chance ?

    >
    > No, it's defined to be 0.
    >
    > It does not violate any constraint that I can see, and the meaning
    > depends solely on whether 0.0 "compares equal to 0". I can't find any
    > justification for 0.0 not comparing equal to 0. [snip elaboration]


    Because of the vagaries of how floating point is represented,
    I believe it is possible in principle for 0.0 to be seen as
    true (that is, != 0) in a conforming implementation, if that
    implementation (a) does not have an exact FP representation for zero,
    and (b) has implementation-defined rounding rules which are defined
    suitably. AFAIK both (a) and (b) may be true in a conforming
    implementation, that is, I don't know of any requirement that
    prevents the possibility of either (or of both together).

    Of course, I don't know of any ACTUAL implementation for which
    even just (a) holds, but just theoretically I think it is possible.
    Tim Rentsch, Jul 21, 2012
    #14
  15. Xavier Roche

    Tim Rentsch Guest

    Re: expressions, evaluations, and values (was: What shall return "0.0 ? 1 : 0" ?)

    -berlin.de (Stefan Ram) writes:

    > Keith Thompson <> writes:
    >>An expression *yields* a value. (I think earlier versions of the
    >>standard used the word "return" for the results of expressions in
    >>some places; as far as I know it's been cleaned up.)

    >
    > I'd say that an expression /had/ a value (and that an /evaluation/
    > yielded a value). Let me try to find quotations in N1570:
    >
    > >>Its lifetime begins when the expression is evaluated

    > and its initial value is the value of the expression.<<
    > -----------------------
    > >>An actual implementation need not evaluate part of an

    > expression if it can deduce that its value is not used
    > and that no needed side effects are produced<<
    >
    > >>the value of CHAR_MIN<<

    >
    > >>expressions with implementation-defined values<<

    >
    > >>Its lifetime begins when the expression is evaluated

    > and its initial value is the value of the expression.<<
    >
    > >>If an expression of any other type is evaluated as a

    > void expression, its value or designator is discarded.<<
    >
    > The relationship between an expression and its value in all
    > these quotes (selected without bias) is always /possessive/,
    > hence /has/. [snip]


    There are also lots of places where the Standard uses phrasing like
    'an expression yields the value ...' or 'x[3][5] yields ...'.
    Generally speaking the Standard often doesn't do a good job of
    observing the distinction between translation-time properties and
    execution-time properties. Strictly speaking, an expression is a
    translation-time entity; it is only an evaulation of an expression
    that has (or yields) a value, or evaluating an expression that yields
    a value. Some expressions have the property that every time they are
    evaluated the evaluations always yield the same value, and there it
    might be more defensible to say that the expression /has/ that value.
    But I don't think the Standard itself is careful about these
    distinctions one way or the other.
    Tim Rentsch, Jul 21, 2012
    #15
  16. Xavier Roche

    Tim Rentsch Guest

    Keith Thompson <> writes:

    > pete <> writes:
    >> Keith Thompson wrote:
    >>> -berlin.de (Stefan Ram) writes:
    >>> > Xavier Roche <> writes:
    >>> >>Is there a C standard expert who can confirm what shall return
    >>> >>0.0 ? 1 : 0
    >>> >
    >>> > An expression does not return. A function may return. After
    >>> >
    >>> > int f(){ return 0.0 ? 1 : 0; {
    >>> >
    >>> > , we can say that f >>shall return 0.0 ? 1 : 0 <<.
    >>>
    >>> An expression *yields* a value. (I think earlier versions of the
    >>> standard used the word "return" for the results of expressions in
    >>> some places; as far as I know it's been cleaned up.)

    >>
    >> Section "6.5 Expressions" in both C89 and in C99,
    >> described the bitwise operators as returning values.

    >
    > C99 says they "return" values; N1256 says they "yield" values,
    > as does N1570 (the C11 pre-release draft). [snip]


    Yes, and N1124 is like N1256 in this regard.
    Tim Rentsch, Jul 21, 2012
    #16
  17. Tim Rentsch <> wrote:

    > I believe it is possible in principle for 0.0 to be seen as
    > true (that is, != 0) in a conforming implementation, if that
    > implementation (a) does not have an exact FP representation for
    > zero, and (b) has implementation-defined rounding rules which
    > are defined suitably. AFAIK both (a) and (b) may be true in a
    > conforming implementation, that is, I don't know of any
    > requirement that prevents the possibility of either (or of both
    > together).


    There is one. An implementation (a) would not suffice C99 5.2.4.2.2
    "Characteristics of floating types <float.h>"; esp. the sum used to
    define a floating-point number gives 0 if f(k) = 0 for all
    1 <= k <= p.

    -- Ralf
    Ralf Damaschke, Jul 22, 2012
    #17
  18. Tim Rentsch <> writes:

    > Ben Bacarisse <> writes:
    >
    >> Xavier Roche <> writes:
    >>
    >>> Hi folks!
    >>>
    >>> Is there a C standard expert who can confirm what shall return
    >>> 0.0 ? 1 : 0
    >>>
    >>> With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result
    >>> is.. 1.

    >>
    >> How odd.
    >>
    >>> Is the result undefined by the standard, by chance ?

    >>
    >> No, it's defined to be 0.
    >>
    >> It does not violate any constraint that I can see, and the meaning
    >> depends solely on whether 0.0 "compares equal to 0". I can't find any
    >> justification for 0.0 not comparing equal to 0. [snip elaboration]

    >
    > Because of the vagaries of how floating point is represented,
    > I believe it is possible in principle for 0.0 to be seen as
    > true (that is, != 0) in a conforming implementation, if that
    > implementation (a) does not have an exact FP representation for zero,
    > and (b) has implementation-defined rounding rules which are defined
    > suitably. AFAIK both (a) and (b) may be true in a conforming
    > implementation, that is, I don't know of any requirement that
    > prevents the possibility of either (or of both together).


    I took the characteristics of floating point numbers presented in
    5.2.4.2.2 to mean that C had to use a representation that includes (an
    exact) zero.

    But, as you say, it turns out that an implementation is not required to
    represent exactly even exactly representable floating constants.
    Fortunately, this must be documented so in the absence of any such
    explanation, 0.0 will be equal to 0.

    > Of course, I don't know of any ACTUAL implementation for which
    > even just (a) holds, but just theoretically I think it is possible.


    Well, I thought not, but it doesn't matter anyway as far as I can see.
    Even if zero is representable, 0.0 can convert to any one of three
    values according to 6.4.4.2 p3.

    --
    Ben.
    Ben Bacarisse, Jul 22, 2012
    #18
  19. Xavier Roche

    Tim Rentsch Guest

    Ralf Damaschke <> writes:

    > Tim Rentsch <> wrote:
    >
    >> I believe it is possible in principle for 0.0 to be seen as
    >> true (that is, != 0) in a conforming implementation, if that
    >> implementation (a) does not have an exact FP representation for
    >> zero, and (b) has implementation-defined rounding rules which
    >> are defined suitably. AFAIK both (a) and (b) may be true in a
    >> conforming implementation, that is, I don't know of any
    >> requirement that prevents the possibility of either (or of both
    >> together).

    >
    > There is one. An implementation (a) would not suffice C99 5.2.4.2.2
    > "Characteristics of floating types <float.h>"; esp. the sum used to
    > define a floating-point number gives 0 if f(k) = 0 for all
    > 1 <= k <= p.


    If you read the footnote to 5.2.4.2.2 p1, and also 5.2.4.2.2 p3,
    I think you'll agree that the condition you describe need not
    be an actual representable value in a particular conforming
    implementation. The value does exist in the model, but the
    model may not reflect what the implementation actually uses,
    and even if it does, the implementation might not provide FP
    numbers with f(1) == 0. Needless to say, I did consult this
    section (and these paragraphs) before making my earlier
    comments. So I still think it's possible for an implementation
    to not have zero as a representable FP value.
    Tim Rentsch, Jul 22, 2012
    #19
  20. Xavier Roche

    Tim Rentsch Guest

    Ben Bacarisse <> writes:

    > Tim Rentsch <> writes:
    >
    >> Ben Bacarisse <> writes:
    >>
    >>> Xavier Roche <> writes:
    >>>
    >>>> Hi folks!
    >>>>
    >>>> Is there a C standard expert who can confirm what shall return
    >>>> 0.0 ? 1 : 0
    >>>>
    >>>> With gcc 4.3/Linux, the result is 0. With Visual C++2010, the result
    >>>> is.. 1.
    >>>
    >>> How odd.
    >>>
    >>>> Is the result undefined by the standard, by chance ?
    >>>
    >>> No, it's defined to be 0.
    >>>
    >>> It does not violate any constraint that I can see, and the meaning
    >>> depends solely on whether 0.0 "compares equal to 0". I can't find any
    >>> justification for 0.0 not comparing equal to 0. [snip elaboration]

    >>
    >> Because of the vagaries of how floating point is represented,
    >> I believe it is possible in principle for 0.0 to be seen as
    >> true (that is, != 0) in a conforming implementation, if that
    >> implementation (a) does not have an exact FP representation for zero,
    >> and (b) has implementation-defined rounding rules which are defined
    >> suitably. AFAIK both (a) and (b) may be true in a conforming
    >> implementation, that is, I don't know of any requirement that
    >> prevents the possibility of either (or of both together).

    >
    > I took the characteristics of floating point numbers presented in
    > 5.2.4.2.2 to mean that C had to use a representation that includes (an
    > exact) zero.
    >
    > But, as you say, it turns out that an implementation is not required to
    > represent exactly even exactly representable floating constants.
    > Fortunately, this must be documented so in the absence of any such
    > explanation, 0.0 will be equal to 0.
    >
    >> Of course, I don't know of any ACTUAL implementation for which
    >> even just (a) holds, but just theoretically I think it is possible.

    >
    > Well, I thought not, but it doesn't matter anyway as far as I can see.
    > Even if zero is representable, 0.0 can convert to any one of three
    > values according to 6.4.4.2 p3.


    I had read this paragraph earlier, but either I misread it or
    I missed the full implications of what it says. I expected
    that any FP constant that could be represented exactly must
    necessarily be given that exact value, but now that you point
    it out obviously it doesn't. So this isn't just a theoretical
    problem -- it's only QOI that saves us from some very surprising
    results.

    Thank you for following up with this observation. Yet another
    strange corner of C that I didn't realize was so strange.
    Tim Rentsch, Jul 22, 2012
    #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. walala
    Replies:
    1
    Views:
    475
  2. Wolfgang Schmidt
    Replies:
    2
    Views:
    486
    Wolfgang Schmidt
    Mar 2, 2004
  3. bronby
    Replies:
    6
    Views:
    374
    Jacob
    Apr 22, 2005
  4. bronby
    Replies:
    3
    Views:
    345
    Gordon Beaton
    Jul 11, 2005
  5. Robert Dober
    Replies:
    8
    Views:
    142
    Robert Dober
    Jun 23, 2009
Loading...

Share This Page