order of printf

Discussion in 'C Programming' started by happy, Jan 9, 2010.

  1. happy

    happy Guest

    Please clear my one doubt

    #include<stdio.h>
    int main(void)
    {
    printf("1") + printf("2") * printf("3\n");
    }

    Here order of evaluation operands of + and * operators is not fixed.

    But I wanted to know that during evaluating these operands (here the 3
    printfs), do these printfs also print ( so
    output can be different 123 or 231 etc.) or they just evaluate their
    arguments i.e. "1", "2" and "3" and output
    will always be 123?
     
    happy, Jan 9, 2010
    #1
    1. Advertising

  2. happy

    Seebs Guest

    On 2010-01-09, happy <> wrote:
    > Please clear my one doubt
    >
    > #include<stdio.h>
    > int main(void)
    > {
    > printf("1") + printf("2") * printf("3\n");
    > }
    >
    > Here order of evaluation operands of + and * operators is not fixed.
    >
    > But I wanted to know that during evaluating these operands (here the 3
    > printfs), do these printfs also print ( so
    > output can be different 123 or 231 etc.) or they just evaluate their
    > arguments i.e. "1", "2" and "3" and output
    > will always be 123?


    Assume that we correct the program to:
    printf("1") + printf("2") * printf("3");
    printf("\n");

    (Otherwise, if 3 printed first, there would be no newline after the others,
    and on some systems that behaves surprisingly.)

    Given this, any of the permutations are possible. My guess is that
    the most common would be 123, 321, and 231.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
     
    Seebs, Jan 9, 2010
    #2
    1. Advertising

  3. On Sat, 9 Jan 2010 09:02:06 -0800 (PST), happy <>
    wrote:

    >Please clear my one doubt
    >
    >#include<stdio.h>
    >int main(void)
    >{
    > printf("1") + printf("2") * printf("3\n");
    >}
    >
    >Here order of evaluation operands of + and * operators is not fixed.
    >
    >But I wanted to know that during evaluating these operands (here the 3
    >printfs), do these printfs also print ( so
    >output can be different 123 or 231 etc.) or they just evaluate their
    >arguments i.e. "1", "2" and "3" and output
    >will always be 123?


    Absent undefined behavior or pathological cases, printf always prints.
    Since stdout usually buffered, whether you see the output is
    implementation defined unless the buffer is flushed.

    The order of operand evaluation is unspecified. The only guarantee is
    that the operands are evaluated before the operation is performed. The
    three calls to printf can be performed in any of six possible
    sequences.

    One (unlikely if the compiler does any optimization) is
    call with "1" and save return value (V1)
    call with "2" and save return value (V2)
    call with "3\n"
    compute V2 * returned value
    compute V1 + previous product
    In this case your output would be "123\n".

    A more likely sequence is
    call with "2" and save return value (V1)
    call with "3\n"
    compute V1 * returned value and save (V2)
    call with "1"
    compute V2 + returned value
    In this case your output would be "23\n1"

    --
    Remove del for email
     
    Barry Schwarz, Jan 9, 2010
    #3
  4. happy

    Stefan Ram Guest

    Barry Schwarz <> writes:
    >Absent undefined behavior or pathological cases, printf always prints.
    >Since stdout usually buffered, whether you see the output is
    >implementation defined unless the buffer is flushed.


    Even if it is flushed, the visibility still might not be given if
    the last line is not terminated by a terminating new-line character.

    »Whether the last line[ of a text stream] requires a
    terminating new-line character is implementation-defined.«
    (»7.19.2 Streams«)
     
    Stefan Ram, Jan 9, 2010
    #4
  5. Barry Schwarz <> writes:

    > On Sat, 9 Jan 2010 09:02:06 -0800 (PST), happy <>
    > wrote:
    >
    >>Please clear my one doubt
    >>
    >>#include<stdio.h>
    >>int main(void)
    >>{
    >> printf("1") + printf("2") * printf("3\n");
    >>}
    >>
    >>Here order of evaluation operands of + and * operators is not fixed.
    >>
    >>But I wanted to know that during evaluating these operands (here the 3
    >>printfs), do these printfs also print ( so
    >>output can be different 123 or 231 etc.) or they just evaluate their
    >>arguments i.e. "1", "2" and "3" and output
    >>will always be 123?

    >
    > Absent undefined behavior or pathological cases, printf always prints.
    > Since stdout usually buffered, whether you see the output is
    > implementation defined unless the buffer is flushed.


    The output /is/ flushed (in this example, at least). What is
    implementation defined is the effect of a final output line with no
    '\n' at the end (which is one possible outcome).

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Jan 9, 2010
    #5
  6. Ben Bacarisse <> writes:
    > Barry Schwarz <> writes:
    >
    >> On Sat, 9 Jan 2010 09:02:06 -0800 (PST), happy <>
    >> wrote:
    >>
    >>>Please clear my one doubt
    >>>
    >>>#include<stdio.h>
    >>>int main(void)
    >>>{
    >>> printf("1") + printf("2") * printf("3\n");
    >>>}
    >>>
    >>>Here order of evaluation operands of + and * operators is not fixed.
    >>>
    >>>But I wanted to know that during evaluating these operands (here the 3
    >>>printfs), do these printfs also print ( so
    >>>output can be different 123 or 231 etc.) or they just evaluate their
    >>>arguments i.e. "1", "2" and "3" and output
    >>>will always be 123?

    >>
    >> Absent undefined behavior or pathological cases, printf always prints.
    >> Since stdout usually buffered, whether you see the output is
    >> implementation defined unless the buffer is flushed.

    >
    > The output /is/ flushed (in this example, at least). What is
    > implementation defined is the effect of a final output line with no
    > '\n' at the end (which is one possible outcome).


    No, what is implementation defined is whether the '\n' at the end the
    output is required. If the implementation says it's not required, the
    output is flushed when the program terminates, and the behavior is
    well defined (though what the environment does with the output might
    not be). If the implementation says it is required, then the behavior
    of the program is undefined, simply because the standard doesn't
    define the behavior. (The implementation may, but isn't required to,
    define the behavior anyway.)

    --
    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, Jan 9, 2010
    #6
  7. Keith Thompson <> writes:

    > Ben Bacarisse <> writes:
    >> Barry Schwarz <> writes:
    >>> On Sat, 9 Jan 2010 09:02:06 -0800 (PST), happy <>
    >>> wrote:

    <snip>
    >>>>#include<stdio.h>
    >>>>int main(void)
    >>>>{
    >>>> printf("1") + printf("2") * printf("3\n");
    >>>>}
    >>>>
    >>>>Here order of evaluation operands of + and * operators is not fixed.
    >>>>
    >>>>But I wanted to know that during evaluating these operands (here the 3
    >>>>printfs), do these printfs also print ( so
    >>>>output can be different 123 or 231 etc.) or they just evaluate their
    >>>>arguments i.e. "1", "2" and "3" and output
    >>>>will always be 123?
    >>>
    >>> Absent undefined behavior or pathological cases, printf always prints.
    >>> Since stdout usually buffered, whether you see the output is
    >>> implementation defined unless the buffer is flushed.

    >>
    >> The output /is/ flushed (in this example, at least). What is
    >> implementation defined is the effect of a final output line with no
    >> '\n' at the end (which is one possible outcome).

    >
    > No, what is implementation defined is whether the '\n' at the end the
    > output is required. If the implementation says it's not required, the
    > output is flushed when the program terminates, and the behavior is
    > well defined (though what the environment does with the output might
    > not be). If the implementation says it is required, then the behavior
    > of the program is undefined, simply because the standard doesn't
    > define the behavior. (The implementation may, but isn't required to,
    > define the behavior anyway.)


    I am not persuaded that a program's behaviour is undefined in the
    specific case where an implementation requires a newline at the end of
    the output and none is present. Can you say more about why you
    believe it is?

    I know it is not normative, but wouldn't you expect this case to be
    listed in sec. 2 of Appendix J if the intent were for such programs to
    have undefined behaviour?

    Your argument is that the standard does not define the behaviour, but
    would say that is does. I would say that it defines the behaviour of

    #include <stdio.h>

    int main(void) { printf("No newline"); }

    as well as it possibly can, regardless of any extra requirements that
    the implementation may put on the stream.

    --
    Ben.
     
    Ben Bacarisse, Jan 9, 2010
    #7
  8. Ben Bacarisse <> writes:
    > Keith Thompson <> writes:
    >> Ben Bacarisse <> writes:

    [...]
    >>> The output /is/ flushed (in this example, at least). What is
    >>> implementation defined is the effect of a final output line with no
    >>> '\n' at the end (which is one possible outcome).

    >>
    >> No, what is implementation defined is whether the '\n' at the end the
    >> output is required. If the implementation says it's not required, the
    >> output is flushed when the program terminates, and the behavior is
    >> well defined (though what the environment does with the output might
    >> not be). If the implementation says it is required, then the behavior
    >> of the program is undefined, simply because the standard doesn't
    >> define the behavior. (The implementation may, but isn't required to,
    >> define the behavior anyway.)

    >
    > I am not persuaded that a program's behaviour is undefined in the
    > specific case where an implementation requires a newline at the end of
    > the output and none is present. Can you say more about why you
    > believe it is?
    >
    > I know it is not normative, but wouldn't you expect this case to be
    > listed in sec. 2 of Appendix J if the intent were for such programs to
    > have undefined behaviour?
    >
    > Your argument is that the standard does not define the behaviour, but
    > would say that is does. I would say that it defines the behaviour of
    >
    > #include <stdio.h>
    >
    > int main(void) { printf("No newline"); }
    >
    > as well as it possibly can, regardless of any extra requirements that
    > the implementation may put on the stream.


    What else could it mean for an implementation to "require" the
    newline to be present?

    The standard allows an implementation to impose a certain
    requirement, that the last line of a text stream must have a
    terminating newline character. But it says nothing about how this
    requirement might be enforce, or, equivalently, about what happens
    if a program violates the requirement. It doesn't even say that
    the resulting behavior is implementation-defined; it just fails to
    define it.

    I can imagine your program on such an implementation not writing
    the last line, writing only a partial line, implicitly appending a
    newline (because the underlying system requires it), having printf
    return a negative value to indicate an error, or creating a corrupted
    text file that can't be read. I see nothing in the standard that
    forbids any of those behavior, or any other behavior.

    Perhaps it wasn't intended to make the behavior undefined (the
    omission from Annex J is telling), but in the absence of any
    definition of the behavior, I'd say the behavior is undefined.

    If it's defined, how would you say it's defined?

    --
    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, Jan 10, 2010
    #8
  9. Keith Thompson <> writes:

    > Ben Bacarisse <> writes:
    >> Keith Thompson <> writes:
    >>> Ben Bacarisse <> writes:

    > [...]
    >>>> The output /is/ flushed (in this example, at least). What is
    >>>> implementation defined is the effect of a final output line with no
    >>>> '\n' at the end (which is one possible outcome).
    >>>
    >>> No, what is implementation defined is whether the '\n' at the end the
    >>> output is required. If the implementation says it's not required, the
    >>> output is flushed when the program terminates, and the behavior is
    >>> well defined (though what the environment does with the output might
    >>> not be). If the implementation says it is required, then the behavior
    >>> of the program is undefined, simply because the standard doesn't
    >>> define the behavior. (The implementation may, but isn't required to,
    >>> define the behavior anyway.)

    >>
    >> I am not persuaded that a program's behaviour is undefined in the
    >> specific case where an implementation requires a newline at the end of
    >> the output and none is present. Can you say more about why you
    >> believe it is?
    >>
    >> I know it is not normative, but wouldn't you expect this case to be
    >> listed in sec. 2 of Appendix J if the intent were for such programs to
    >> have undefined behaviour?
    >>
    >> Your argument is that the standard does not define the behaviour, but
    >> would say that is does. I would say that it defines the behaviour of
    >>
    >> #include <stdio.h>
    >>
    >> int main(void) { printf("No newline"); }
    >>
    >> as well as it possibly can, regardless of any extra requirements that
    >> the implementation may put on the stream.

    >
    > What else could it mean for an implementation to "require" the
    > newline to be present?


    My view is that it would be up to the implementation what it means but
    that that meaning is beyond the reach of the C standard. Had the
    committee intended to make such situations undefined I think they
    would have said so. They want to give permission for an implementation
    to "mess up" in this case (provided it documents that it might) but
    they don't want to say any more than that. It would have been so easy
    to add another instance if UB explicitly at this point that the
    absence is, to me, telling.

    > The standard allows an implementation to impose a certain
    > requirement, that the last line of a text stream must have a
    > terminating newline character. But it says nothing about how this
    > requirement might be enforce, or, equivalently, about what happens
    > if a program violates the requirement. It doesn't even say that
    > the resulting behavior is implementation-defined; it just fails to
    > define it.


    I don't think it is so clear-cut. It fails to define the consequences
    of a requirement.

    > I can imagine your program on such an implementation not writing
    > the last line, writing only a partial line, implicitly appending a
    > newline (because the underlying system requires it), having printf
    > return a negative value to indicate an error, or creating a corrupted
    > text file that can't be read. I see nothing in the standard that
    > forbids any of those behavior, or any other behavior.


    I think my program must do all the things specified for a similar
    program that has a putchar('\n'); after the printf except it does not
    do the putchar. At least that seems to me a reasonable reading of the
    standard. I agree with most of your possibilities except the last
    one: "any other behaviour".

    It all boils down to whether something that the implementation
    requires is as significant as something the standard requires.

    > Perhaps it wasn't intended to make the behavior undefined (the
    > omission from Annex J is telling), but in the absence of any
    > definition of the behavior, I'd say the behavior is undefined.
    >
    > If it's defined, how would you say it's defined?


    By the sections covering printf, program termination and so on.
    Characters are transmitted to the host environment, but because they
    do not meet a requirement of the implementation, the host environment
    is permitted to do pretty much anything it like with it. I don't see
    that it is permitted to anything not related to that data.

    I am aware that this is a less than satisfactory argument.

    --
    Ben.
     
    Ben Bacarisse, Jan 10, 2010
    #9
  10. Ben Bacarisse <> writes:
    > Keith Thompson <> writes:
    >> Ben Bacarisse <> writes:
    >>> Keith Thompson <> writes:
    >>>> Ben Bacarisse <> writes:

    >> [...]
    >>>>> The output /is/ flushed (in this example, at least). What is
    >>>>> implementation defined is the effect of a final output line with no
    >>>>> '\n' at the end (which is one possible outcome).
    >>>>
    >>>> No, what is implementation defined is whether the '\n' at the end the
    >>>> output is required. If the implementation says it's not required, the
    >>>> output is flushed when the program terminates, and the behavior is
    >>>> well defined (though what the environment does with the output might
    >>>> not be). If the implementation says it is required, then the behavior
    >>>> of the program is undefined, simply because the standard doesn't
    >>>> define the behavior. (The implementation may, but isn't required to,
    >>>> define the behavior anyway.)
    >>>
    >>> I am not persuaded that a program's behaviour is undefined in the
    >>> specific case where an implementation requires a newline at the end of
    >>> the output and none is present. Can you say more about why you
    >>> believe it is?
    >>>
    >>> I know it is not normative, but wouldn't you expect this case to be
    >>> listed in sec. 2 of Appendix J if the intent were for such programs to
    >>> have undefined behaviour?
    >>>
    >>> Your argument is that the standard does not define the behaviour, but
    >>> would say that is does. I would say that it defines the behaviour of
    >>>
    >>> #include <stdio.h>
    >>>
    >>> int main(void) { printf("No newline"); }
    >>>
    >>> as well as it possibly can, regardless of any extra requirements that
    >>> the implementation may put on the stream.

    >>
    >> What else could it mean for an implementation to "require" the
    >> newline to be present?

    >
    > My view is that it would be up to the implementation what it means but
    > that that meaning is beyond the reach of the C standard. Had the
    > committee intended to make such situations undefined I think they
    > would have said so. They want to give permission for an implementation
    > to "mess up" in this case (provided it documents that it might) but
    > they don't want to say any more than that. It would have been so easy
    > to add another instance if UB explicitly at this point that the
    > absence is, to me, telling.


    "Beyond the reach of the C standard" is *exactly* what "undefined
    behavior" means. It doesn't mean that the program will misbehave in
    some gruesome manner; it merely means that the standard doesn't say
    how it behaves.

    See also C99 4p2:

    If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside
    of a constraint is violated, the behavior is undefined. Undefined
    behavior is otherwise indicated in this International Standard by
    the words ‘‘undefined behavior’’ or by the omission of any
    explicit definition of behavior. There is no difference in
    emphasis among these three; they all describe ‘‘behavior that is
    undefined’’.

    >> The standard allows an implementation to impose a certain
    >> requirement, that the last line of a text stream must have a
    >> terminating newline character. But it says nothing about how this
    >> requirement might be enforce, or, equivalently, about what happens
    >> if a program violates the requirement. It doesn't even say that
    >> the resulting behavior is implementation-defined; it just fails to
    >> define it.

    >
    > I don't think it is so clear-cut. It fails to define the consequences
    > of a requirement.


    It "fails to define" (i.e., leaves undefined) the consequences (i.e.,
    the behavior).

    >> I can imagine your program on such an implementation not writing
    >> the last line, writing only a partial line, implicitly appending a
    >> newline (because the underlying system requires it), having printf
    >> return a negative value to indicate an error, or creating a corrupted
    >> text file that can't be read. I see nothing in the standard that
    >> forbids any of those behavior, or any other behavior.

    >
    > I think my program must do all the things specified for a similar
    > program that has a putchar('\n'); after the printf except it does not
    > do the putchar. At least that seems to me a reasonable reading of the
    > standard.


    That would be the required behavior for an implementation that
    *doesn't* require the trailing newline.

    > I agree with most of your possibilities except the last
    > one: "any other behaviour".


    But most of the possibilities I mentioned are inconsistent with what
    you just said.

    > It all boils down to whether something that the implementation
    > requires is as significant as something the standard requires.
    >
    >> Perhaps it wasn't intended to make the behavior undefined (the
    >> omission from Annex J is telling), but in the absence of any
    >> definition of the behavior, I'd say the behavior is undefined.
    >>
    >> If it's defined, how would you say it's defined?

    >
    > By the sections covering printf, program termination and so on.
    > Characters are transmitted to the host environment, but because they
    > do not meet a requirement of the implementation, the host environment
    > is permitted to do pretty much anything it like with it. I don't see
    > that it is permitted to anything not related to that data.


    I don't see anything that says the consequences are limited to those
    related to that data.

    The behavior isn't unspecified, because the standard doesn't provide
    two or more possibilities. It isn't implementation-defined, because
    the standard doesn't require the implementation to document the
    behavior, only to document whether the newline is required.

    > I am aware that this is a less than satisfactory argument.


    Agreed. :cool:}

    --
    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, Jan 10, 2010
    #10
  11. happy

    Nick Guest

    Barry Schwarz <> writes:

    > On Sat, 9 Jan 2010 09:02:06 -0800 (PST), happy <>
    > wrote:
    >
    >>Please clear my one doubt
    >>
    >>#include<stdio.h>
    >>int main(void)
    >>{
    >> printf("1") + printf("2") * printf("3\n");
    >>}
    >>
    >>Here order of evaluation operands of + and * operators is not fixed.
    >>
    >>But I wanted to know that during evaluating these operands (here the 3
    >>printfs), do these printfs also print ( so
    >>output can be different 123 or 231 etc.) or they just evaluate their
    >>arguments i.e. "1", "2" and "3" and output
    >>will always be 123?

    >
    > Absent undefined behavior or pathological cases, printf always prints.
    > Since stdout usually buffered, whether you see the output is
    > implementation defined unless the buffer is flushed.
    >
    > The order of operand evaluation is unspecified. The only guarantee is
    > that the operands are evaluated before the operation is performed. The
    > three calls to printf can be performed in any of six possible
    > sequences.
    >
    > One (unlikely if the compiler does any optimization) is
    > call with "1" and save return value (V1)
    > call with "2" and save return value (V2)
    > call with "3\n"
    > compute V2 * returned value
    > compute V1 + previous product
    > In this case your output would be "123\n".


    Exactly what GCC with no optimisation produces.

    > A more likely sequence is
    > call with "2" and save return value (V1)
    > call with "3\n"
    > compute V1 * returned value and save (V2)
    > call with "1"
    > compute V2 + returned value
    > In this case your output would be "23\n1"


    GCC resolutely produces "123" for every optimisation level (-o0 to -o3).
    Yes, I'm surprised too. I wondered if it was being so clever that it's
    not even doing the arithmetic. I tried keeping the result (always 2 of
    course) and printing it with the final \n, but it didn't alter things.
    I'm not interested enough to get really clever and make the results of
    the printfs beyond GCC's knowledge (using * parameters and random
    strings perhaps) to see if that makes any difference.

    My version of the code shown below just in case I'm being really silly:

    #include <stdio.h>
    #include <stdlib.h>

    int main(void) {
    int x = printf("1") + printf("2") * printf("3");
    printf("\t%d\n",x);
    return EXIT_SUCCESS;
    }
    --
    Online waterways route planner | http://canalplan.eu
    Plan trips, see photos, check facilities | http://canalplan.org.uk
     
    Nick, Jan 10, 2010
    #11
  12. Keith Thompson <> writes:

    > Ben Bacarisse <> writes:
    >> Keith Thompson <> writes:
    >>> Ben Bacarisse <> writes:
    >>>> Keith Thompson <> writes:
    >>>>> Ben Bacarisse <> writes:
    >>> [...]
    >>>>>> The output /is/ flushed (in this example, at least). What is
    >>>>>> implementation defined is the effect of a final output line with no
    >>>>>> '\n' at the end (which is one possible outcome).
    >>>>>
    >>>>> No, what is implementation defined is whether the '\n' at the end the
    >>>>> output is required. If the implementation says it's not required, the
    >>>>> output is flushed when the program terminates, and the behavior is
    >>>>> well defined (though what the environment does with the output might
    >>>>> not be). If the implementation says it is required, then the behavior
    >>>>> of the program is undefined, simply because the standard doesn't
    >>>>> define the behavior. (The implementation may, but isn't required to,
    >>>>> define the behavior anyway.)
    >>>>
    >>>> I am not persuaded that a program's behaviour is undefined in the
    >>>> specific case where an implementation requires a newline at the end of
    >>>> the output and none is present. Can you say more about why you
    >>>> believe it is?
    >>>>
    >>>> I know it is not normative, but wouldn't you expect this case to be
    >>>> listed in sec. 2 of Appendix J if the intent were for such programs to
    >>>> have undefined behaviour?
    >>>>
    >>>> Your argument is that the standard does not define the behaviour, but
    >>>> would say that is does. I would say that it defines the behaviour of
    >>>>
    >>>> #include <stdio.h>
    >>>>
    >>>> int main(void) { printf("No newline"); }
    >>>>
    >>>> as well as it possibly can, regardless of any extra requirements that
    >>>> the implementation may put on the stream.
    >>>
    >>> What else could it mean for an implementation to "require" the
    >>> newline to be present?

    >>
    >> My view is that it would be up to the implementation what it means but
    >> that that meaning is beyond the reach of the C standard. Had the
    >> committee intended to make such situations undefined I think they
    >> would have said so. They want to give permission for an implementation
    >> to "mess up" in this case (provided it documents that it might) but
    >> they don't want to say any more than that. It would have been so easy
    >> to add another instance if UB explicitly at this point that the
    >> absence is, to me, telling.

    >
    > "Beyond the reach of the C standard" is *exactly* what "undefined
    > behavior" means.


    Yes, I expressed myself badly by making it so easy to find me saying
    that!

    First off, I have no argument against that "it'd not specified so it's
    undefined argument". In that sense, I should stop here and accept
    that you are right but I can't shake the nagging doubts. Specifically
    that this case is missing from Appendix J2 and the unique wording that
    is used for this instance. So the best I can do is accept that you
    are right: it's undefined.

    Permit me, though, to say what I think may have happened if for no
    other reason than to try to explain my badly worded previous
    explanations.

    I think it is possible that the intent was to make this
    implementation-defined but someone pointed out that this would require
    the standard to list the possible behaviours so that the
    implementation's choice can be documented (as per 3.4.1 and 3.4.4).
    Making it explicitly undefined seemed rather excessive so the
    ingenious language of making implementation defined whether a final
    newline is required was used.

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Jan 10, 2010
    #12
  13. Francis Glassborow <> writes:
    > Ben Bacarisse wrote:

    [...]

    Summary of discussion so far:

    C99 7.19.2p2 says:

    A text stream is an ordered sequence of characters composed into
    _lines_, each line consisting of zero or more characters plus a
    terminating new-line character. Whether the last line requires a
    terminating new-line character is implementation-defined.

    I argue that if an implementation says that the terminating new-line
    is required, and a program fails to provide it, then that program's
    behavior is undefined when running under that implementation. Ben
    reluctantly agrees. (The quoted text was getting too long; please let
    me know if this summary is inaccurate.)

    >> Permit me, though, to say what I think may have happened if for no
    >> other reason than to try to explain my badly worded previous
    >> explanations.
    >>
    >> I think it is possible that the intent was to make this
    >> implementation-defined but someone pointed out that this would require
    >> the standard to list the possible behaviours so that the
    >> implementation's choice can be documented (as per 3.4.1 and 3.4.4).
    >> Making it explicitly undefined seemed rather excessive so the
    >> ingenious language of making implementation defined whether a final
    >> newline is required was used.

    >
    > I agree. This area has always made me feel a bit uncomfortable. The
    > added problem is what happens if a final \n is not required. One way
    > that the implementation can handle this is by adding one anyway. Now I
    > have programs (not source code but already compiled programs) which
    > would barf if the termination of a data file was wrong. No newline at
    > the end of the file is fatal and and empty line at the end of the file
    > also causes problems.


    If the final new-line is not required, I was about to say the behavior
    is specified by the portions of the standard that describe the
    behavior of stdio calls. If the program doesn't write a new-line to
    the stream, no new-line is written to the stream. But as I was
    writing this, I went back and read the remainder of the paragraph.
    It includes the following:

    Data read in from a text stream will necessarily compare equal to
    the data that were earlier written out to that stream only if: the
    data consist only of printing characters and the control
    characters horizontal tab and new-line; no new-line character is
    immediately preceded by space characters; and the last character
    is a new-line character.

    So, regardless of whether that trailing new-line is required, if the
    program doesn't provide one, the data written needn't come back
    identically when it's read. An implementation *can* implicitly append
    a new-line to the end of the stream if it needs to (or just because it
    wants to). For example, a text file might be stored on disk in a way
    that can't represent a missing trailing new-line (say, as a sequence
    of fixed-length or variable-length records, where the '\n' character
    is generated on input).

    (On all the implementations I've used, the trailing new-line is not
    required and is not implicitly generated, and a text file can end
    in an unterminated line.)

    > That creates a portability issue for any programs I write as tools to
    > create the data that these third party programs will use. Of course I
    > have a small tool that ensures that the data files are indeed
    > correctly terminated but that should not be necessary and adds just
    > one more task that has to be carried out and makes it just a bit more
    > awkward for others wishing to do the same thing (it relates to
    > creating Bridge deals in PBN or DLM formats and so is of use to very
    > basic computer users preparing hands for their clubs)


    The standard explicitly gives itself permission to make some
    behavior undefined without saying so, just by neglecting to define
    the behavior; see C99 4p2. I always find it a little disturbing
    when it does so (it tends to lead to long debates like this one),
    and would be more comfortable if it said explicitly that the behavior
    is undefined. In fact, I think I'd like to see the phrase "or by
    the omission of any explicit definition of behavior" dropped, and
    all implicit undefined behavior made explicit. If the standard
    neither defines the behavior for something nor says that it's
    undefined, that would be an error in the standard. I understand
    that this would be a significant amount of work, and since I'm not
    volunteering to do it, I won't complain too loudly if it's not done.

    In this particular case, it's likely that the authors didn't
    actually intend to make the behavior undefined; they added some
    wording to allow for odd systems that need the trailing new-line,
    but didn't follow through on the consequences.

    One possible "fix" for this would be to require that, if omitting the
    trailing new-line would cause problems, the implementation *must*
    add one (or do something that has the same effect). This wouldn't
    be too difficult to implement. Keep a flag, associated with the
    stream, that indicates whether the last thing written to the stream
    was a new-line. If that flag is not set when the stream is closed,
    write a new-line to the stream before closing it. Most systems
    wouldn't even have to do this much, since they don't require the
    trailing new-line.

    --
    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, Jan 10, 2010
    #13
  14. happy

    Stefan Ram Guest

    Keith Thompson <> writes:
    >One possible "fix" for this would be to require that, if omitting the
    >trailing new-line would cause problems, the implementation *must*
    >add one (or do something that has the same effect). This wouldn't


    It is possible that sometimes under an implementation this might
    cause »problems«, but still other times is needed under the same
    implementation.

    Thus, I'd leave it as it is and teach that text files should /always/
    be new-line terminated in maximally portable code, and only be
    non-terminated in implementation specific code, when this is needed.

    BTW: Since the I/O-system of C++ is based on C I/O (as I understand
    it), all of this discussion applies to C++, too. But C++ programmers
    rarely appreciate the need to think about this, because material from
    C90 to them appear to be somewhat far-fetched.
     
    Stefan Ram, Jan 10, 2010
    #14
  15. happy

    Kaz Kylheku Guest

    On 2010-01-10, Francis Glassborow <> wrote:
    > I agree. This area has always made me feel a bit uncomfortable. The
    > added problem is what happens if a final \n is not required. One way
    > that the implementation can handle this is by adding one anyway.


    Only in the case that the program invoked undefined behavior by
    not supplying that newline.

    > Now I
    > have programs (not source code but already compiled programs) which
    > would barf if the termination of a data file was wrong. No newline at
    > the end of the file is fatal and and empty line at the end of the file
    > also causes problems.


    A C implementation must not add an extra blank line to the end of a
    properly terminated text stream; there is no newline-related undefined
    behavior then.

    If the text stream is not properly terminated, it can do anything at
    all. Well, don't invoke that situation!
     
    Kaz Kylheku, Jan 10, 2010
    #15
  16. happy

    Kaz Kylheku Guest

    On 2010-01-10, Francis Glassborow <> wrote:
    > Kaz Kylheku wrote:
    >> On 2010-01-10, Francis Glassborow <> wrote:
    >>> I agree. This area has always made me feel a bit uncomfortable. The
    >>> added problem is what happens if a final \n is not required. One way
    >>> that the implementation can handle this is by adding one anyway.

    >>
    >> Only in the case that the program invoked undefined behavior by
    >> not supplying that newline.

    >
    > No, check elsethread.


    Even if the implementation has a document which says that ``a newline is
    not required at the end of a text stream''. the behavior of leaving it
    out is still undefined in the C language. Implementation definitions of
    extended behavior don't back-propagate into the language, otherwise
    we would have to come to the conclusion that, for instance,
    __attribute__ ((aligned (16)) is defined in C, due being defined in
    GNU C.

    >> A C implementation must not add an extra blank line to the end of a
    >> properly terminated text stream; there is no newline-related undefined
    >> behavior then.
    >>
    >> If the text stream is not properly terminated, it can do anything at
    >> all. Well, don't invoke that situation!

    >
    > Again check.


    You have run into some kind of library bug. Which system is this that
    adds the extra newline?

    I can't find anything in the C to substantiate the concern that a
    conforming library may add extra blank lines to a text file if the
    program hasn't invoked undefined behavior, and has obeyed certain other
    restrictions on writing to a text stream:

    7.19.2 Streams

    ...

    Data read in from a text stream will necessarily compare equal to
    the data that were earlier written out to that stream only if:
    the data consist only of printing characters and the
    control characters horizontal tab and new-line; no new-line
    character is immediately preceded by space characters; and the
    last character is a new-line character. Whether space characters
    that are written out immediately before a new-line character
    appear when read in is implementation-defined.
     
    Kaz Kylheku, Jan 11, 2010
    #16
  17. happy

    Tim Rentsch Guest

    Keith Thompson <> writes:

    > [long message about 7.19.2p2 means undefined behavior when
    > a newline is not written in an implementation whose last
    > lines require a newline.]


    Here's another point of view. There is never undefined behavior
    regardless of whether a newline is written or not. Here's
    paragraph 2 in 7.19.2 again:

    A text stream is an ordered sequence of characters composed into
    _lines_, each line consisting of zero or more characters plus a
    terminating new-line character. Whether the last line requires
    a terminating new-line character is implementation-defined.
    Characters may have to be added, altered, or deleted on input and
    output to conform to differing conventions for representing text
    in the host environment. Thus, there need not be a one-to-one
    correspondence between the characters in a stream and those in
    the external representation. Data read in from a text stream
    will necessarily compare equal to the data that were earlier
    written out to that stream only if: the data consist only of
    printing characters and the control characters horizontal tab
    and new-line; no new-line character is immediately preceded by
    space characters; and the last character is a new-line
    character. Whether the space characters that were written out
    immediately before a new-line character appear when read in is
    implementation-defined.

    What this paragraph means is

    1. It's always guaranteed that reading a text stream will read
    the same bytes that were written if the three conditions are
    observed;

    2. An implementation may also guarantee that reading a text
    stream will read the same bytes that were written even if
    spaces are written just before newline characters;

    3. An implementation may also guarantee that reading a text
    stream will read the same bytes that were written even if
    characters were written on a last line but no final newline
    was written;

    4. Whether conditions (2) and (3) hold are each independently
    implementation-defined.

    The semantics of writing to a text stream is always defined -- output
    is written to stream/file in question. (Similarly the semantics of
    reading is always defined.) What bytes actually appear in the file
    (ie, its external representation) is _not_ defined, so the Standard
    needs to say what would get read in again. 7.19.2p2 is only about
    when subsequent reads are guaranteed to read the same bytes as were
    written, and nothing else.

    Read the language in 7.19.2p2 carefully, I expect y'all will reach the
    same conclusion. Note that the semantics of reading and writing are
    defined in their respective sections; and that there are no 'shall'
    or 'shall not' statements in 7.19.2p2 to violate (nor are there any
    violated in the rest of 7.19 as far as I know).
     
    Tim Rentsch, Jan 13, 2010
    #17
    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. ben
    Replies:
    4
    Views:
    634
    Martin Ambuhl
    Jun 26, 2004
  2. whatluo

    (void) printf vs printf

    whatluo, May 26, 2005, in forum: C Programming
    Replies:
    29
    Views:
    1,288
  3. marsarden

    the order of printf parameter

    marsarden, Jan 11, 2006, in forum: C Programming
    Replies:
    6
    Views:
    313
    marsarden
    Jan 16, 2006
  4. azza

    printf affects following printf/s

    azza, Oct 17, 2010, in forum: C Programming
    Replies:
    0
    Views:
    450
  5. guru
    Replies:
    8
    Views:
    292
Loading...

Share This Page