Assigning double constant to integer types

Discussion in 'C Programming' started by dev, Apr 17, 2009.

  1. dev

    dev Guest

    When i do int x=2.2;

    Is this behaviour undefined.?
    K & R says that it may draw a warning but it is not illegal....

    now one more point--
    Can a legal behaviour be undefined?
    or vice versa,I mean that can a undefined behavior be legal?
     
    dev, Apr 17, 2009
    #1
    1. Advertisements

  2. dev

    jameskuyper Guest

    There's no restrictions on warnings. A conforming compiler is
    permitted to print a message saying "Warning: code compiled between
    02:00 and 05:00 - code qualify may be low."
    The standard never talks about legality. When people talk about
    something being illegal in C, they are generally referring to one of
    the following:
    * An non-conforming implementation
    * Code which contains a syntax error
    * Code which contains constraint violation
    * Code which has undefined behavior
    * Code which exceeds minimim implementation limits

    Keep in mind that the standard does not penalize any of the things
    above; it merely labels them, which is why "legality" is not really a
    relevant concept. Implementations are allowed to be non-conforming.
    Code is allowed to have syntax errors, constraint violations, or
    undefined behavior. Code is allowed to exceed implementation limits.
    Code which has any or all of those characteristics can be translated
    and executed by a conforming implmentation - and it might even do what
    it's developer intended it to do, though I would strongly recommend
    not relying upon that.

    The statement
    int x = 2.2;
    does not, in itself, qualify under any of those categories.
     
    jameskuyper, Apr 17, 2009
    #2
    1. Advertisements

  3. A conforming compiler is even allowed to have typos in its warning
    messages. :cool:}
     
    Keith Thompson, Apr 17, 2009
    #3
  4. dev

    jameskuyper Guest

    Kenneth Brody wrote:
    ....
    A conforming compiler isn't even required to generate error messages
    in any language that anybody knows how to read. Even if they can be
    read, they aren't required to identify either the location in the code
    where a problem was detected, nor the nature of the problem that was
    detected; which is just as well, because they also aren't required to
    be truthful. This is all considered a matter of QoI.
     
    jameskuyper, Apr 17, 2009
    #4
  5. There's no requirement not to output diagnostics for code without
    errors, so outputting that for all programs would be conforming. But,
    like the "one program" implementation discussed in another thread, it
    doesn't matter. The requirement to produce diagnostics for errors
    seems to have the desired effect in the real world.

    -- Richard
     
    Richard Tobin, Apr 17, 2009
    #5
  6. dev

    jacob navia Guest

    Requirements of the standard reflect the attitude in general
    that the standard has about error handling.

    Nothing is required, error handling and meaningful diagnostics
    are just optional.

    In my implementation I have tried to improve the error messages
    and there is a lot of code in lcc-win with no other purpose than to
    produce meaningful error messages.

    For instance the terms "lvalue" is banned and instead of saying
    expression is not an lvalue
    I say
    You can't assign to " expr "

    trying to make error messages more clear.

    Mostly, a missing semicolon is diagnosted as such, without having
    a cascade of errors that do not say what the actual error is.
     
    jacob navia, Apr 17, 2009
    #6
  7. dev

    jameskuyper Guest

    The standard doesn't have attitudes, it's just a piece of paper. It's
    the committee members that have attitudes.
    This doesn't reflect the attitudes so much as the mission of the C
    committee. One of their most fundamental goals is to standardize
    existing practice, and existing practice with regard to the text of
    error and warning messages was, and remains, too chaotic to allow much
    standarization. I'm sure that the committee members are just as much a
    fan of clearer and more accurate diagnostics as any of us - after all,
    many of them are developers, just like most of us. As much as anything
    else, the lack of specification is intended to allow and encourage the
    development of better diagnostics. It's certainly the case that the
    diagnostics I get from today's C compilers are much clearer and much
    more likely to correctly identify the cause of the problem than the
    ones I got 30 years ago.

    If the committee had decided in 1987 to be a lot more specific about
    the contents of diagnostic messages, they would almost certainly have
    mandated something a lot closer to the diagnostics I got 30 years ago,
    than to the messages I get from modern compilers. The fact that they
    were mandated would surely have hindered development of better
    diagnostics than those mandated by the standard.

    The standard's rather lax requirements allow a fully conforming
    compiler to be created for a new platform relatively easily, which is
    one of key reasons why C is one of the most widely implemented
    languages. Development of a compiler version with a higher QoI can be
    put off until after the new platform has attracted a sufficiently
    large customer base to justify the costs associated with implementing
    the higher QoI.
    Wonderful! Thats the case in my code too, and I don't think anyone on
    the committee doesn't appreciate the importants of that. But there's a
    difference between appreciating good diagnostics, and mandating them.
     
    jameskuyper, Apr 17, 2009
    #7
  8. dev

    jfbode1029 Guest

    No.

    "6.7.8.11: The initializer for a scalar shall be a single expression,
    optionally enclosed in braces. The initial value of the object is that
    of the expression (after conversion); *the same type constraints and
    conversions as for simple assignment apply*, taking the type of the
    scalar
    to be the unqualified version of its declared type."

    Emphasis mine.

    In this case, the floating-point value 2.2 will be converted to the
    integer value 2, which will then be assigned to x. The compiler *may*
    issue a warning (initializing an int variable with a non-integer value
    is a sign that someone isn't paying attention to what they're doing),
    but the behavior is certainly well-defined.
    Well, here's how the standard defines "undefined behavior":

    "behavior, upon use of a *nonportable or erroneous program construct
    or of erroneous data*, for which this International Standard imposes
    no requirements"

    Emphasis mine. To me, "nonportable" != "illegal", so I'd be willing
    to say yes, there are "legal" behaviors that are technically
    undefined.
     
    jfbode1029, Apr 17, 2009
    #8
  9. dev

    jacob navia Guest

    Standardize existing practice? Remember the discussion about
    complex numbers? Existing practice was the "i" suffix. The standard
    invented a new notation.

    Errors like:

    Missing return value from a non void function
    Missing prototype
    Too much / Too little arguments passed to a function
    Return used with a void function
    Implicit declaration of a symbol

    and many other constraints could have been put in a
    core diagnostics package that would represent warnings or
    errors that all users could count on.

    The existing situation is that most compilers will diagnose
    some of those but not all, each compiler has a different subset
    and you can't trust the compiler to always catch those errors.
     
    jacob navia, Apr 17, 2009
    #9
  10. All conforming compilers must diagnose all constraint violations -- or
    at least must issue at least one diagnostic for any translation unit
    containing at least one constraint violation or syntax error. Any
    compiler can become confused if there are too many errors, or if it
    guess incorrectly about what you meant. Handling cascading errors
    intelligently is certainly a good thing, but I don't think the
    standard can or should require it. For example, a compiler
    implementer might concentrate on diagnosing the *first* error and
    providing a very fast compile-fix-recompile cycle; I might not want
    such a thing myself, but I don't think it should be considered
    non-conforming.

    I'm not sure what you mean by "a core diagnostics package".

    If you're suggesting that the standard should mandate the *form* of
    diagnostics, I don't think that's either practical or desirable. The
    language issue alone (English vs. French vs. ...) would have to be
    handled; also, it might be desirable for diagnostics to fit in with
    the rest of the operating system.

    If you mean that some things that currently are not constraint
    violations should be, I might agree with you. Let's go through your
    list (not in order):

    -- Missing return value from a non void function
    -- Return used with a void function

    We already have the following constraints (C99 6.8.6.4p1):

    A return statement with an expression shall not appear in a
    function whose return type is void. A return statement without an
    expression shall only appear in a function whose return type is
    void.

    A "return;" within a void function is perfectly legitimate; it's
    redundant if it appears just before the closing "}", but I'm not
    convinced that should be a constraint violation.

    Reaching the closing "}" of a non-void function is a problem. The
    standard currently makes this undefined behavior if the result is
    used; this is largely for backward compatibility (pre-ANSI C didn't
    have "void"), but we could probably drop that. But if it's a
    constraint, then it has to be detected at compile time -- which means
    that the compiler would have to detect that there is no execution path
    that reaches the closing "}". For example, this would be a constraint
    violation:

    int foo(void) {
    if (condition_that_never_happens) {
    fputs("Oops!", stderr);
    }
    else {
    return 1;
    }
    }

    But what about this?

    int foo(int n) {
    if (n < 0) return -1;
    if (n == 0) return 0;
    if (n > 0) return 1;
    }

    It can't ever reach the closing "}", and a sufficiently clever
    optimizing compiler might detect that, but should all C compilers be
    required to do so? Even if they should, it's hard to imagine how this
    requirement would be worded, let alone implemented.

    Furthermore, the compiler would have to know that exit() and abort()
    terminate the current function. And I'm not even going to think about
    raise() and longjmp(), or implementation-defined functions that do
    similar things.

    Or you could just require that any non-void function must contain at
    least one "return <expr>;" statement, which might catch some but not
    all problems. But then a lazy programmer could write:

    int foo(void) {
    if (0) return 0;
    /* blah blah */
    }

    -- Missing prototype
    -- Too much / Too little arguments passed to a function

    Support for unprototyped functions was necessary for compatibility
    with pre-ANSI compilers. The committee apparently felt that 1999 was
    too soon to require prototypes for all functions, and I tend to agree
    with that decision. But C99 dropped implicit function declarations,
    and non-prototype declarations are obsolescent.

    -- Implicit declaration of a symbol

    Is there a case of this that's not already a constraint violation in
    C99?
     
    Keith Thompson, Apr 17, 2009
    #10
  11. dev

    jacob navia Guest

    This is just meaningless, as we have discussed several times.
    It suffices for the compiler to issue one "diagnostic" like

    "This program may contain errors"

    and that single diagnostic makes it conforming...
    A set of constraints violation that must have as a consequence
    that the compiler emits a diagnostic for each of them.
    look, I said explicitly that the form wasn't important!
    This is typical of K Thompson. Take one sentence and twist it
    to give something absurd. Then asking:

    Is that what you want?

    Obviously when I use

    "return used with a void function" I mean a return expression.
    That is just polemic.
    This could be avoided with a standard way of annotating the compiler,
    another widespread need that has been solved differently in different
    compilers and cries for a solution in the standard.

    GNU uses the

    __attribute__(feature)

    syntax, and Microsoft uses

    __declspec(attribute)
    syntax.


    Using one of those we could just write

    __declspec(notreached);

    and be done with it.

    This is another subject and another discussion of course,
    I just note the inactivity of the committee in this
    subject. Microsoft has introduced an extended syntax for
    marking up the function arguments with in/out and in/out
    parameters (what is a good idea). Gcc has used the
    __attribute__ syntax for alignment and many other things.

    If we had a standard all that could be written PORTABLY

    See above

    [snip]

    Yes, in the case of a function call. I meant the
    declaration

    a;

    with implicit meaning

    int a;
     
    jacob navia, Apr 17, 2009
    #11
  12. dev

    jameskuyper Guest

    There was very little existing practice with complex numbers. There
    was lots and LOTS of existing practice with diagnostics, and it was
    almost impossible to write a description sufficiently vague not render
    almost all implementations non-conforming, without also making it too
    vague to be of any use. The committee settled for mandating only one
    thing: the existence of at least one diagnostic message for any
    program with certain types of problems that could be easily identified
    by the compiler at compile time. Anything more detailed than that
    would have been impractical.
    "core" diagnostics, as you describe them, are possibly the only
    desirable aspect of diagnostics that the standard has provided: those
    are the diagnostics that are mandatory, as I've described above, and
    there's quite a few of them; including (at least in C99) several of
    the cases you've listed.
    You can trust a conforming compiler to catch any problem for which a
    diagnostic is mandatory.
     
    jameskuyper, Apr 17, 2009
    #12
  13. It's not meaningless. That's *exactly* what it means.

    If you want the standard to provide more stringent requirements for
    diagnostics, the best way to make that happen would be to propose new
    wording for those requirements. I'm not saying that expressing
    dissatisfaction with the current state of affairs is a bad thing, but
    it's only the first step.

    In my opinion (and yes, I know you disagree), the standard's current
    wording is adequate. A conforming implementation could produce a
    single diagnostic for all translation units -- but in practice none
    actually do so. From what I've seen most existing compilers do
    produce reasonably decent diagnostics.

    If it were easy to modify the standard to require more than it does
    now, I'd be all for it -- but I don't think it would be easy. And
    since the purpose of such a change would be to require implementations
    to do what they already do, I personally don't think it would be worth
    the effort.
    Ok. I wouldn't have chose the phrase "core diagnostics package" for
    that idea, but I'll accept it.

    Do you mean that *all* constraint violations in each translation unit
    must be diagnosed, or do you propose that each of some defined subset
    of constraint violations must be diagnosed? (In the latter case, if a
    translation unit contains two constraint violations that aren't in the
    core set, a single diagnostic would be sufficient.) If the latter,
    how would you determine which constraints belong to this core set?

    I'm not attacking your idea here, I'm just asking for clarification.

    If you mean that a compiler must diagnose all constraint violations in
    a translation unit, I think that would be difficult to specify in many
    cases, let alone to implement.

    Consider this, for example:

    int main(void)
    {
    short float f;
    float *p = &f;
    return 0;
    }

    The "short float" violates the constraint of 6.7.2p2. But is
    "float *p = &f;" a constraint violation or not? If f were of type
    short, it would be; if f were of type float, it wouldn't be. The
    compiler can't reasonably guess the programmer's intent here.

    One constraint violation can, in some cases, make it difficult or
    impossible to correctly interpret the code that follows it and to
    detect further constraint violations. Syntax errors, of course, are
    even worse.

    In my opinion, compiler implementers (yourself included) are already
    motivated to diagnose as many errors as possible. Requiring it in the
    standard might be nice, but I honestly don't think it's necessary.
    But if you can come up with proposed wording that's an improvement
    over what the standard says now, I'd love to see it, and I'll be glad
    to help by looking for problems in it.
    I just re-read your article. I suggest you read-read it yourself.
    You said no such thing. If I missed it, please point it out to me.
    And this is, unfortunately, quite typical of you. (Incidentally, most
    people here call me Keith, and you're welcome to do likewise. Your
    habit of calling me by my last name when you're mad at me is
    annoying.)

    I merely asked for clarification. My own words are rarely as clear on
    the screen as they were in my head.
    No, I merely asked for clarification. I'm not a mind-reader. I
    merely assumed that you meant what you said. It was not as obvious as
    you seem to think it was.
    Then by all means feel free to present a concrete proposal.
    For example, consider this:

    int foo(int n) {
    if (n < 0) {
    /* Serious error, give up */
    exit(EXIT_FAILURE);
    }
    else {
    return n + 1;
    }
    }

    If I understand you correctly (and *please* correct me if I don't),
    this would require a diagnostic because the function might terminate
    without executing a return statement (and the compiler doesn't
    necessarily know what exit() does). But adding
    __declspec(notreached);
    would inhibit the diagnostic.

    Which means that code that's currently perfectly valid would become a
    constraint violation. The committee, quite properly, takes a dim view
    of breaking existing code.

    I wouldn't mind seeing something like what you're proposing in a
    future standard, but you've got to accept constructive criticism.
    Huh? "a;" doesn't mean "int a;" in C99; implicit int was dropped,
    remember? (I'm not even sure that "a;" means "int a;" in C90, but
    since we're talking about possible future changes to the standard,
    that's hardly relevant.) And implicit function declarations were
    removed as well. See page xii in the foreword.

    Is this why you've never made a clear statement that lcc-win fully
    conforms to C99? If you don't understand what the standard says, how
    can you say whether your compiler conforms to it?
     
    Keith Thompson, Apr 17, 2009
    #13
  14. dev

    jameskuyper Guest

    You're objecting to the wording of that message? Do you really want a
    committee dominated by English speakers to impose requirements on the
    wording of the messages for a Hindi compiler? Or even a French
    compiler, for that matter?

    ....
    As Keith has already pointed out, all constraints in the current
    standard have, as a consequence, that the compiler must emit a
    diagnostic. Requiring more than one diagnostic would impose
    unacceptable burdens on quick-and-dirty compilers for new platforms
    that halt processing as soon as they detect the first serious error.
    The generation of a separate diagnostic for each violation is a minor
    luxury that can safely be left to QoI to resolve; this has worked very
    well so far - can you name any major compiler that provides only the
    single diagnostic required by the standard? Can you name any compiler,
    major or not, which does so?

    Also, in my experience, the first serious error message usually
    correctly identifies at least one real problem in the code; it's not
    uncommon for a large number of the other messages to be side-effects
    of the same problem. As a result, I often take a close look only at
    the first diagnostic, fix the corresponding problem, and then
    recompile to find the next problem; this is often quicker than wading
    through a sea of side-effect messages looking for the next one that
    represents a truly distinct defect in my code. It was quite different
    in the old days when compiling my programs took a long time, but with
    modern systems and modern compilers I can recompile much faster than I
    can fix the defects.

    ....
    There's no such thing in C as a return expression. There is such a
    thing as a return statement. Keith (and I) assumed you were referring
    to a return statement. If you weren't referring to a return statement,
    what were you referring to?

    ....
    C99 doesn't support that - he explicitly asked about C99.
     
    jameskuyper, Apr 17, 2009
    #14
  15. dev

    CBFalconer Guest

    It could output "nuqDaq ta' SoH pol lIj yuch" for each and every
    source line, and still be conforming. Not extremely useful,
    though.
     
    CBFalconer, Apr 18, 2009
    #15
  16. dev

    CBFalconer Guest

    I was under the impression that you were using the C99 standard.
    Have you changed your mind?
     
    CBFalconer, Apr 18, 2009
    #16
  17. Oh, but it is. It establishes a minimal criterion for conformance.
    Most or all real-world implementations, in the process of satisfying
    the standard's requirement, go far beyond it anyway.

    But even ignoring that, it means that an implementation that produces
    no diagnostics is non-conforming. That's a real purpose.

    The current wording does its job. What exactly would be the purpose
    of adding more stringent requirements? That's not a rhetorical
    question; if you have a good answer I'd like to see it.
    Not at all. As far as I know all existing implementations already do
    this.
    And anything not on that list would be non-conforming? You're sure
    that nobody will come up with new ways to provide this information
    that the committee hasn't thought of?

    I wouldn't object to a requirement that a diagnostic must give some
    indication of where the problem occurred. I see no need to specify
    how it should do so.
    Then a compiler could abort after the first diagnostic. Your
    objection is that the standard allows a mininal implementation, isn't
    it?

    It's difficult to know how such a requirement could be enforced. How
    can you know that a compiler detected a violation but didn't report
    it? And why would it not report it anyway, with or without a
    requirement?
    Hmm. Personally, I'd like a compiler that cites chapter and verse
    from the standard in its diagnostics, but I wouldn't want to require
    all compilers to do so -- and I know that's not what you suggested.
    The point is that I'm concerned that a requirement for diagnostics to
    distinguish among different constraints might forbid some very useful
    error reporting strategies.

    Compiler writers *want* their diagnostics to be useful. I think that
    market pressure has done far more to give us good diagnostics than any
    reasonable set of requirements in the standard would. And any
    requirements that went beyond existing universal practice would render
    some reasonable implementations non-conforming.

    Here's a thought. Show us a small program with a constraint
    violation, and a diagnostic message from a real-world compiler that
    you think is so inadequate that the compiler *should* be considered
    non-conforming. Tell us how you'd modify C99 5.1.1.3 to require that
    compiler to produce an acceptable diagnostic. For reference, here's
    C99 5.1.1.3:

    A conforming implementation shall produce at least one
    diagnostic message (identified in an implementation-defined
    manner) if a preprocessing translation unit or translation
    unit contains a violation of any syntax rule or constraint,
    even if the behavior is also explicitly specified as undefined
    or implementation-defined. Diagnostic messages need not be
    produced in other circumstances.

    And there's also a footnote (obviously this is non-normative):

    The intent is that an implementation should identify the nature
    of, and where possible localize, each violation. Of course,
    an implementation is free to produce any number of diagnostics
    as long as a valid program is still correctly translated. It
    may also successfully translate an invalid program.

    I also suggest reading section 5.1.1.3 of the Rationale,
    <http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf>;
    it's long enough that Im not going to quote it here.
     
    Keith Thompson, Apr 18, 2009
    #17
  18. dev

    Eric Sosman Guest

    You *think* you'd like such a compiler, but trust me:
    You wouldn't. I've used one, and it was an experience worth
    missing. Every diagnostic included three or four lines of
    direct quotes from the Standard, with section numbers, so
    one simple typo could produce enough diagnostic output to
    rival "War And Peace." Ugh, ugh, ugh.
     
    Eric Sosman, Apr 18, 2009
    #18
  19. Citing may indeed be excessive, but I like tendra's references:

    $ tcc -c test.c
    "test.c", line 2: Warning:
    [ISO 6.1.2.2]: 'i' previously declared with external linkage (at line 1).

    "test.c", line 5: Error:
    [ISO 6.5]: 'j' has already been declared (at line 4).

    No flood of messages this way, but you can look up what exactly the standard
    says if/when you need to.
     
    Harald van Dijk, Apr 18, 2009
    #19
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.