• Re: is "x *= ++f * ++f" a valid statement ?

    From Andrey Tarasevich@3:633/280.2 to All on Wed Jun 19 11:53:03 2024
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer

    --
    Best regards,
    Andrey

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Wed Jun 19 12:27:00 2024
    On 5/23/24 10:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For a built in type, the behavior of the two ++ operations on f are
    unordered, and that will lead to undefined behavior.

    If f is of a user defined type, with an operator++ defined, I think
    while the order the two operations is unspecified, they can't get
    intermixed, so I think it may just be unspecified behavior, and no nasal demons allowed.

    There is no requirement for the implementation to define the behavior,
    and it doesn't need to be consistant.


    "Valid" would be a question of semantics. There is nothing that requires
    a diagnostic, and the implementation has no grounds for not creating a program. but for built in types, there is no requirements on what
    happens, and for user types the order things happen is unspecified.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From Bonita Montero@3:633/280.2 to All on Thu Jun 20 01:40:44 2024
    Am 19.06.2024 um 03:53 schrieb Andrey Tarasevich:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer

    You feel uncertain for nothing.



    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 07:55:20 2024
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    ++f could be defined as exit(0) for some UDT.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sat Jun 22 08:10:50 2024
    On 6/21/24 5:55 PM, olcott wrote:
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    ++f could be defined as exit(0) for some UDT.


    But, the DEFINITON of ++ doesn't requring that one of the f's are
    incremented first, then you use the value, then the othero one. (unless
    the rules were actually changed).

    x *= ++f + ++f

    could be implemented as

    f = f+1;
    f = f+1;

    x *= f * f;

    it could even be done as
    ;
    tf1 = f+1
    tf2 = f+1;

    x *= tf1 + tf2;

    f = tf1;
    f = tf2;

    so, we have no promise that f even increases by 2


    At least this is what it could be under the original rules. I would have
    to see if it was tightened when threading was allowed.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 09:06:53 2024
    On 6/21/2024 5:10 PM, Richard Damon wrote:
    On 6/21/24 5:55 PM, olcott wrote:
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    ++f could be defined as exit(0) for some UDT.


    But, the DEFINITON of ++ doesn't requring that one of the f's are incremented first, then you use the value, then the othero one. (unless
    the rules were actually changed).


    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.


    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sat Jun 22 10:14:08 2024
    On 6/21/24 7:06 PM, olcott wrote:
    On 6/21/2024 5:10 PM, Richard Damon wrote:
    On 6/21/24 5:55 PM, olcott wrote:
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    ++f could be defined as exit(0) for some UDT.


    But, the DEFINITON of ++ doesn't requring that one of the f's are
    incremented first, then you use the value, then the othero one.
    (unless the rules were actually changed).


    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.



    Sure it can, because the order of the parts of the operation of the two
    ++f is unspecified. In fact, the implementation doesn't need to define
    it at all, it is just unspecified (and it used to invoke Undefined
    Behavior, I am not sure if that clause is still there)

    Detail explaination of the operation of ++f has effectively 4 steps

    1) read the value of f
    2) increment the value read
    3) write that value back into f
    4) use that value in the expression

    Sequence wise, we have that 1 is before 2 is before 3, and 2 is before
    4, but 3 and 4 are not ordered with respect to one another.

    And, the sequence of operations between the two different ++f operations
    have no sequeenc between each other, only that both of their step 4 are working at the same time to make the final result of that operation.

    Thus, both reads of the value might occur before either write backs of
    either updated value, and thus f is only increased by 1 by the statement.

    In fact, the optimizer could well see that option and just read the
    value once increment it once, and write it back just once.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sat Jun 22 10:35:52 2024
    olcott <polcott333@gmail.com> writes:
    On 6/21/2024 5:10 PM, Richard Damon wrote:
    On 6/21/24 5:55 PM, olcott wrote:
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    Yes, it's syntactically valid, but that wasn't the question.

    ++f could be defined as exit(0) for some UDT.

    But, the DEFINITON of ++ doesn't requring that one of the f's are
    incremented first, then you use the value, then the othero
    one. (unless the rules were actually changed).


    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    We don't have to assume anything. The meaning of "*=" is well known
    (and you left out the fact that x is evaluated only once).

    It doesn't have implementation-defined behavior. It has undefined
    behavior. The C++ standard says so:

    If a side effect on a memory location is unsequenced relative to
    either another side effect on the same memory location or a value
    computation using the value of any object in the same memory
    location, and they are not potentially concurrent, the behavior is
    undefined.

    If x and f are objects of type int, then the evaluation of `++f * ++f`
    has undefined behavior because the two modifications of f are
    unsequenced. There isn't some limited number of possible behaviors.
    The standard says nothing about what happens when the expression is
    evaluated.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Sat Jun 22 13:42:18 2024
    On 6/21/24 7:06 PM, olcott wrote:
    ....
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself, undefined behavior, independent of what larger expression it might be
    part of. "implementation-defined behavior" is defined by the standard as "behavior, for a well-formed program construct and correct data, that
    depends on the implementation and that each implementation documents"
    (3.13). Since this program is not well formed, implementations have no obligation to document what it's behavior will be, so it cannot be implementation-defined behavior.

    Repeating what I said in an earlier message (with one minor correction):

    "Except where noted, evaluations of operands of individual operators and
    of subexpressions of individual expressions are unsequenced." (6.9.1p10)

    Both ++f expressions are sub-expressions of the multiplication
    expression. Thus, the executions are unsequenced, which is not, in
    itself, a problem. However, they both have a side effect on the same
    memory location, and that is a problem, because that same clause goes on
    to say:

    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is undefined."

    These two expressions are not potentially concurrent: they are in the
    same expression, so they must be in the same thread, and if they are in
    a signal handler, they must both be in the same signal handler.
    Therefore, the expression ++f * ++f has undefined behavior.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 13:58:48 2024
    On 6/21/2024 7:35 PM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    On 6/21/2024 5:10 PM, Richard Damon wrote:
    On 6/21/24 5:55 PM, olcott wrote:
    On 6/18/2024 8:53 PM, Andrey Tarasevich wrote:
    On 05/23/24 7:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    The question is meaningless without knowing the types of objects
    involved. It has no specific answer


    If it works correctly for int then it is
    syntactically correct:
    int x = 1;
    int f = 1;
    x = 1 * (2 * 3);

    Yes, it's syntactically valid, but that wasn't the question.

    ++f could be defined as exit(0) for some UDT.

    But, the DEFINITON of ++ doesn't requring that one of the f's are
    incremented first, then you use the value, then the othero
    one. (unless the rules were actually changed).


    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    We don't have to assume anything. The meaning of "*=" is well known
    (and you left out the fact that x is evaluated only once).

    It doesn't have implementation-defined behavior. It has undefined
    behavior. The C++ standard says so:

    If a side effect on a memory location is unsequenced relative to
    either another side effect on the same memory location or a value
    computation using the value of any object in the same memory
    location, and they are not potentially concurrent, the behavior is
    undefined.

    If x and f are objects of type int, then the evaluation of `++f * ++f`
    has undefined behavior because the two modifications of f are
    unsequenced. There isn't some limited number of possible behaviors.
    The standard says nothing about what happens when the expression is evaluated.


    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 14:02:15 2024
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself, undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4

    independent of what larger expression it might be
    part of. "implementation-defined behavior" is defined by the standard as "behavior, for a well-formed program construct and correct data, that
    depends on the implementation and that each implementation documents"
    (3.13). Since this program is not well formed, implementations have no obligation to document what it's behavior will be, so it cannot be implementation-defined behavior.

    Repeating what I said in an earlier message (with one minor correction):

    "Except where noted, evaluations of operands of individual operators and
    of subexpressions of individual expressions are unsequenced." (6.9.1p10)

    Both ++f expressions are sub-expressions of the multiplication
    expression. Thus, the executions are unsequenced, which is not, in
    itself, a problem. However, they both have a side effect on the same
    memory location, and that is a problem, because that same clause goes on
    to say:

    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is undefined."

    These two expressions are not potentially concurrent: they are in the
    same expression, so they must be in the same thread, and if they are in
    a signal handler, they must both be in the same signal handler.
    Therefore, the expression ++f * ++f has undefined behavior.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sat Jun 22 16:18:26 2024
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that. You were wrong. Do you understand that
    now?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From David Brown@3:633/280.2 to All on Sat Jun 22 21:09:50 2024
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this. Neither C nor C++ do (except for specific operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it matters
    what the standards say.



    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 22:38:33 2024
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that. You were wrong. Do you understand that
    now?


    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the
    result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)


    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sat Jun 22 22:40:03 2024
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it matters what the standards say.


    It would be bad for the standards to be counter-intuitive.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sat Jun 22 23:45:24 2024
    On 6/22/24 8:38 AM, olcott wrote:
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that.ÿ You were wrong.ÿ Do you understand that
    now?


    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)



    In this case no, but if the operation was - it would,

    And, as pointed out there is no requirement on the ordering of even the sub-parts except determinism (we can't use a value we haven't computed
    yet). This means the ++ can be interleaved.

    And, because of the EXPLICIT requirement on updates to a value needing
    to be ordered to avoid undefined behavior, the compiler, seeing that
    Undefined Behavior exist there can do ANYTHING it wants with that code.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sat Jun 22 23:56:45 2024
    On 6/22/24 8:40 AM, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself, >>>> undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    No, the Standards are to define the "contract" between the programmer
    and the implementations.

    C (and to a lesser extent C++) were envisioned as "High Performance"
    languages designed to get efficiencies of code close to what could be
    created with pure assembly language. Leaving things unspecified that
    still allow the program to be ABLE to express what he wants, and also
    allowing the compiler to generate the most efficient code possible was
    the goal.

    Forcing a left-to-right (or right-to-left) order for expressions adds
    possible cost to the code generation due to possible need for spilling registers to temporary locations to compute other results.

    If you NEED the specific ordering, you can always pre-compute the sub-expressions to explicit temporaries, so forcing the order isn't that useful\.

    One of the main design ideas was that the program is assumed to be
    competent and knows the language well. (This may be less true for C++)
    and gives the programmer powerful tools that do allow them to shoot
    themselves in the foot.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sun Jun 23 00:13:26 2024
    On 6/22/2024 8:45 AM, Richard Damon wrote:
    On 6/22/24 8:38 AM, olcott wrote:
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that.ÿ You were wrong.ÿ Do you understand that >>> now?


    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the
    result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)



    In this case no, but if the operation was - it would,

    And, as pointed out there is no requirement on the ordering of even the sub-parts except determinism (we can't use a value we haven't computed
    yet). This means the ++ can be interleaved.

    And, because of the EXPLICIT requirement on updates to a value needing
    to be ordered to avoid undefined behavior,

    In other words you fail to comprehend that: (5 * 4) == (4 * 5)

    the compiler, seeing that
    Undefined Behavior exist there can do ANYTHING it wants with that code.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sun Jun 23 00:23:35 2024
    On 6/22/24 10:13 AM, olcott wrote:
    On 6/22/2024 8:45 AM, Richard Damon wrote:
    On 6/22/24 8:38 AM, olcott wrote:
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that.ÿ You were wrong.ÿ Do you understand
    that
    now?


    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the
    result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)



    In this case no, but if the operation was - it would,

    And, as pointed out there is no requirement on the ordering of even
    the sub-parts except determinism (we can't use a value we haven't
    computed yet). This means the ++ can be interleaved.

    And, because of the EXPLICIT requirement on updates to a value needing
    to be ordered to avoid undefined behavior,

    In other words you fail to comprehend that: (5 * 4) == (4 * 5)

    no, the issue is that the two ++f are unsequenced, so one possible
    result (ignore the allowance of total undefined behavior) is (4*4), sine
    the code COULD be compiled to the equivalent of:

    int __t1 = f;
    int __t2 = __t1+1;
    int __t3 = f;
    int __t4 = __t3+1;
    x *= __t2 * __t4;
    f = __t2;
    f = __t4;


    the compiler, seeing that Undefined Behavior exist there can do
    ANYTHING it wants with that code.



    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From David Brown@3:633/280.2 to All on Sun Jun 23 00:52:47 2024
    On 22/06/2024 14:40, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself, >>>> undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    People's "intuition" varies wildly. Pretty much any definition would be counter-intuitive to someone. That's why language standards try to have precise definitions, rather than just saying "it all works pretty much
    like you'd expect".

    We realise the definition of C and C++ expression evaluation does not
    match what you thought was "intuitive". That does not matter - it would
    not matter even if lots of C and C++ programmers agreed with you. What matters for these languages is what their standards /say/. That way, we
    can look at clear facts written in official documents, rather than
    trying to rely on what random people think about to be how they imagine
    things ought to be.

    You can happily feel that C would be better if evaluation order were
    strictly define. Some people will agree with that, others will disagree
    - but it will not make a blind bit of difference to the actual /facts/
    of the matter.



    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sun Jun 23 02:27:33 2024
    On 6/22/2024 9:52 AM, David Brown wrote:
    On 22/06/2024 14:40, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by
    itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    People's "intuition" varies wildly.ÿ Pretty much any definition would be counter-intuitive to someone.ÿ That's why language standards try to have precise definitions, rather than just saying "it all works pretty much
    like you'd expect".

    We realise the definition of C and C++ expression evaluation does not
    match what you thought was "intuitive".ÿ That does not matter - it would
    not matter even if lots of C and C++ programmers agreed with you.ÿ What matters for these languages is what their standards /say/.ÿ That way, we
    can look at clear facts written in official documents, rather than
    trying to rely on what random people think about to be how they imagine things ought to be.

    You can happily feel that C would be better if evaluation order were strictly define.ÿ Some people will agree with that, others will disagree
    - but it will not make a blind bit of difference to the actual /facts/
    of the matter.



    Then make the rule strict left to right unless otherwise specified.
    int x = 2 + 3 * 5; // is otherwise specified by operator precedence.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sun Jun 23 03:20:42 2024
    On 6/22/24 12:27 PM, olcott wrote:
    On 6/22/2024 9:52 AM, David Brown wrote:
    On 22/06/2024 14:40, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your >>>>>> premise has to do with it. The expression ++f * ++f has, all by
    itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    People's "intuition" varies wildly.ÿ Pretty much any definition would
    be counter-intuitive to someone.ÿ That's why language standards try to
    have precise definitions, rather than just saying "it all works pretty
    much like you'd expect".

    We realise the definition of C and C++ expression evaluation does not
    match what you thought was "intuitive".ÿ That does not matter - it
    would not matter even if lots of C and C++ programmers agreed with
    you.ÿ What matters for these languages is what their standards /say/.
    That way, we can look at clear facts written in official documents,
    rather than trying to rely on what random people think about to be how
    they imagine things ought to be.

    You can happily feel that C would be better if evaluation order were
    strictly define.ÿ Some people will agree with that, others will
    disagree - but it will not make a blind bit of difference to the
    actual /facts/ of the matter.



    Then make the rule strict left to right unless otherwise specified.
    int x = 2 + 3 * 5; // is otherwise specified by operator precedence.


    Join the ISO Committe and try to lobby for it.

    There are good reasons it isn't defined that way.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From Chris M. Thomasson@3:633/280.2 to All on Sun Jun 23 05:14:44 2024
    On 6/22/2024 6:56 AM, Richard Damon wrote:
    On 6/22/24 8:40 AM, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by
    itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    No, the Standards are to define the "contract" between the programmer
    and the implementations.

    C (and to a lesser extent C++) were envisioned as "High Performance" languages designed to get efficiencies of code close to what could be created with pure assembly language.
    [...]

    I guess it depends on how one uses C++. It can be just as fast as C,
    with a little "less" work... Fair enough?


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Sun Jun 23 05:48:43 2024
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your
    premise has to do with it. The expression ++f * ++f has, all by itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4

    C is deliberately underspecified, to allow implementations more freedom
    to optimize their code. The key point is that ++f * ++f modifies the
    same object twice without any requirement that the updates occur in a particular order. This means an implementation is allowed to generate
    code that implements those modifications in such a way that they could interfere with each other.

    Consider, for example, an implementation where f is a 64-bit long long
    on a system with no hardware support for types longer than 16 bits, so
    that it needs to generate multiple machine instructions to implement
    ++f. If you were calculating ++f * ++g, it would be entirely feasible to interleave the instructions that calculate ++f and ++g; there might, in
    fact, be some advantage to doing so. When the implementor writes the
    code that implements that interleaving, the fact that ++f * ++f would
    have undefined behavior relieves the implementor of any responsibility
    for checking whether the two ++ operations apply to the same object,
    which simplifies the logic of that code.

    I'm not saying that these rules were chosen with this particular example
    in mind, but only that examples like this one were the reason why C
    takes the general approach that it does: unless otherwise specified,
    operations on sub-expressions are unordered with respect to each other,
    and when an action modifying an object is unordered with respect to
    another operation that either reads or modifies that object, the
    behavior is undefined.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sun Jun 23 10:54:11 2024
    olcott <polcott333@gmail.com> writes:
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.
    You may well have thought that. You were wrong. Do you understand
    that now?

    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the
    result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)

    So no, you don't understand. Do you want to?

    I already quoted the wording from the ISO C++ standard (the document
    that defines the language) that clearly states that the behavior
    is undefined. I'm not trying to convince you that it should or
    shouldn't be, I'm telling you that it is.

    The specification that the behavior is undefined is not based on
    examining some finite number of possible outcomes and determining
    whether they all happen to be the same. The behavior is undefined
    because the two modifications of f are unsequenced.

    Apparently you don't believe me. I can't do anything about that.

    There are valid reasons for the way it's currently defined.
    You don't seem to care about those reasons.

    I had already configured my newsreader to filter out anything
    you post in this newsgroup, but you've changed your email address
    yet again. I plan to update my filter soon.

    (Anyone who takes olcott seriously is advised to take a look at his
    posts in comp.theory.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sun Jun 23 10:55:25 2024
    olcott <polcott333@gmail.com> writes:
    [...]
    Then make the rule strict left to right unless otherwise specified.
    int x = 2 + 3 * 5; // is otherwise specified by operator precedence.

    No.

    Are we done here?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sun Jun 23 12:51:23 2024
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Sun Jun 23 14:51:38 2024
    olcott <polcott333@gmail.com> writes:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.

    It's been explained to you in great detail, and for whatever reason you
    choose not to understand it. For the sake of others who might believe
    you, I urge you to stop.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Mikko@3:633/280.2 to All on Sun Jun 23 18:48:54 2024
    On 2024-06-22 13:45:24 +0000, Richard Damon said:

    On 6/22/24 8:38 AM, olcott wrote:
    On 6/22/2024 1:18 AM, Keith Thompson wrote:
    olcott <polcott333@gmail.com> writes:
    [...]
    That is weird I wold have chosen left to right sequence.
    I thought that the order of arithmetic operations specifies
    left to right sequence.

    You may well have thought that.ÿ You were wrong.ÿ Do you understand that >>> now?


    "x *= ++f * ++f"
    int x = 5;
    int y = 3;

    For the calculation is question is seems to make no difference to the result.
    x = 5 * (4 * 5)
    x = 5 * (5 * 4)



    In this case no, but if the operation was - it would,

    And, as pointed out there is no requirement on the ordering of even the sub-parts except determinism (we can't use a value we haven't computed
    yet). This means the ++ can be interleaved.

    And, because of the EXPLICIT requirement on updates to a value needing
    to be ordered to avoid undefined behavior, the compiler, seeing that Undefined Behavior exist there can do ANYTHING it wants with that code.

    For example, a valid interpretation is to store the value 17 in z.

    --
    Mikko


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: - (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Sun Jun 23 21:32:36 2024
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but the
    storing of the incremented result is allowed to happen at any point
    prior to the end expression it is part of. (In older terms, the sequence point);

    If f was a user defined type, with a user define operator++ then yes, it
    is bracketed with sequencing and the two will not overlap, but not for primative types.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From David Brown@3:633/280.2 to All on Sun Jun 23 22:46:09 2024
    On 22/06/2024 18:27, olcott wrote:
    On 6/22/2024 9:52 AM, David Brown wrote:
    On 22/06/2024 14:40, olcott wrote:
    On 6/22/2024 6:09 AM, David Brown wrote:
    On 22/06/2024 06:02, olcott wrote:
    On 6/21/2024 10:42 PM, James Kuyper wrote:
    On 6/21/24 7:06 PM, olcott wrote:
    ...
    When we assume the *= assigns
    the result of the RHS * the LHS to the LHS
    "x *= ++f * ++f"

    means x = x * (++f * ++f)
    thus cannot have implementation defined behavior.

    You are correct about that conclusion, though I don't see what your >>>>>> premise has to do with it. The expression ++f * ++f has, all by
    itself,
    undefined behavior,

    It would seem to be naturally defined to be Left to right
    ++f from 2 to 3
    ++f from 3 to 4
    3 * 4


    Some programming languages define the order of evaluation for
    subexpressions like this.ÿ Neither C nor C++ do (except for specific
    operators, which do not include multiplication).

    It doesn't really matter what you consider "natural" or not - it
    matters what the standards say.


    It would be bad for the standards to be counter-intuitive.


    People's "intuition" varies wildly.ÿ Pretty much any definition would
    be counter-intuitive to someone.ÿ That's why language standards try to
    have precise definitions, rather than just saying "it all works pretty
    much like you'd expect".

    We realise the definition of C and C++ expression evaluation does not
    match what you thought was "intuitive".ÿ That does not matter - it
    would not matter even if lots of C and C++ programmers agreed with
    you.ÿ What matters for these languages is what their standards /say/.
    That way, we can look at clear facts written in official documents,
    rather than trying to rely on what random people think about to be how
    they imagine things ought to be.

    You can happily feel that C would be better if evaluation order were
    strictly define.ÿ Some people will agree with that, others will
    disagree - but it will not make a blind bit of difference to the
    actual /facts/ of the matter.



    Then make the rule strict left to right unless otherwise specified.
    int x = 2 + 3 * 5; // is otherwise specified by operator precedence.



    What do you mean, "Make the rule" ? /I/ didn't write the C++ or C
    standards - I can't make any rules there. Nor can anyone else here.
    And even if I could, I would not change this. C and C++ made these
    design decisions for good reasons, and I agree with the decision.


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Sun Jun 23 22:59:18 2024
    On 6/23/2024 6:32 AM, Richard Damon wrote:
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but the
    storing of the incremented result is allowed to happen at any point
    prior to the end expression it is part of. (In older terms, the sequence point);

    If f was a user defined type, with a user define operator++ then yes, it
    is bracketed with sequencing and the two will not overlap, but not for primative types.

    It is not f++, it is ++f meaning the the operation must occur before
    the value is accessed.

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Mon Jun 24 04:25:41 2024
    On 6/23/24 8:59 AM, olcott wrote:
    On 6/23/2024 6:32 AM, Richard Damon wrote:
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but the
    storing of the incremented result is allowed to happen at any point
    prior to the end expression it is part of. (In older terms, the
    sequence point);

    If f was a user defined type, with a user define operator++ then yes,
    it is bracketed with sequencing and the two will not overlap, but not
    for primative types.

    It is not f++, it is ++f meaning the the operation must occur before
    the value is accessed.


    But the writing back of the result does not.

    The ++ and -- operators are NOT defined to be in any way "atomic".

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From olcott@3:633/280.2 to All on Mon Jun 24 05:18:13 2024
    On 6/23/2024 1:25 PM, Richard Damon wrote:
    On 6/23/24 8:59 AM, olcott wrote:
    On 6/23/2024 6:32 AM, Richard Damon wrote:
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but the
    storing of the incremented result is allowed to happen at any point
    prior to the end expression it is part of. (In older terms, the
    sequence point);

    If f was a user defined type, with a user define operator++ then yes,
    it is bracketed with sequencing and the two will not overlap, but not
    for primative types.

    It is not f++, it is ++f meaning the the operation must occur before
    the value is accessed.


    But the writing back of the result does not.

    The ++ and -- operators are NOT defined to be in any way "atomic".

    In other words it is not a direct memory increment?

    --
    Copyright 2024 Olcott "Talent hits a target no one else can hit; Genius
    hits a target no one else can see." Arthur Schopenhauer


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Richard Damon@3:633/280.2 to All on Mon Jun 24 06:23:34 2024
    On 6/23/24 3:18 PM, olcott wrote:
    On 6/23/2024 1:25 PM, Richard Damon wrote:
    On 6/23/24 8:59 AM, olcott wrote:
    On 6/23/2024 6:32 AM, Richard Damon wrote:
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but the
    storing of the incremented result is allowed to happen at any point
    prior to the end expression it is part of. (In older terms, the
    sequence point);

    If f was a user defined type, with a user define operator++ then
    yes, it is bracketed with sequencing and the two will not overlap,
    but not for primative types.

    It is not f++, it is ++f meaning the the operation must occur before
    the value is accessed.


    But the writing back of the result does not.

    The ++ and -- operators are NOT defined to be in any way "atomic".

    In other words it is not a direct memory increment?


    Not required to be, since not all computers have one.

    It CAN be, (and may well be on many processors) but isn't required to be.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: i2pn2 (i2pn.org) (3:633/280.2@fidonet)
  • From David Brown@3:633/280.2 to All on Mon Jun 24 17:11:29 2024
    On 23/06/2024 22:23, Richard Damon wrote:
    On 6/23/24 3:18 PM, olcott wrote:
    On 6/23/2024 1:25 PM, Richard Damon wrote:
    On 6/23/24 8:59 AM, olcott wrote:
    On 6/23/2024 6:32 AM, Richard Damon wrote:
    On 6/22/24 10:51 PM, olcott wrote:
    On 5/23/2024 9:14 AM, Bonita Montero wrote:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    For that specific case the result would seem to be identical
    no matter the sequence of the incrementations for int type: f.
    I might not understand this fully.


    Nope, the issue is that increment isn't an atomic operation, but
    the storing of the incremented result is allowed to happen at any
    point prior to the end expression it is part of. (In older terms,
    the sequence point);

    If f was a user defined type, with a user define operator++ then
    yes, it is bracketed with sequencing and the two will not overlap,
    but not for primative types.

    It is not f++, it is ++f meaning the the operation must occur before
    the value is accessed.


    But the writing back of the result does not.

    The ++ and -- operators are NOT defined to be in any way "atomic".

    In other words it is not a direct memory increment?


    Not required to be, since not all computers have one.

    It CAN be, (and may well be on many processors) but isn't required to be.

    Very few modern architectures support direct memory operations now.
    Even ISA's that have instructions that appear to be direct memory
    operations will often split them into separate read, modify and write microops. And for multi-core systems, atomic memory operations are very costly as they involve bus locks and synchronisation - so compilers
    don't generate them unless you specifically ask for them.

    And of course operations like ++f or f++ are very rarely atomic if you
    are using the result of the operation, even if the processor supports an atomic memory increment - you still need to read the memory, before or
    after the increment.


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From testuseri2p@3:633/280.2 to All on Tue Jul 23 03:51:43 2024
    I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: Rocksolid Light (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Tue Jul 23 07:58:14 2024
    what@tf.com (testuseri2p) writes:
    I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.

    That's a little too simple. You can alter a variable multiple times in
    one statement as long as the two modifications are *sequenced*, for
    example if they're separated by a comma operator.

    In the code fragment in the subject line, the two occurrences of "++f"
    are unsequenced, so the behavior is undefined.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Tue Jul 23 11:57:39 2024
    On 7/22/24 13:51, testuseri2p wrote:
    I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.

    The correct (and admittedly more complicated) statement of the relevant
    rule is:
    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is undefined."

    The biggest difference between the exact rule and what you said is that
    two different updates to a variable may occur in the same statement, so
    long as they are sequenced relative to each other. Sub-expressions of an expression are sequenced before evaluation of the expression itself. In general, the sub-expressions of a expression are unsequenced, but there
    several exceptions: ||, &&, ?:, the comma operator.

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which no declaration exists - it is still undefined behavior to write code that
    applies unsequence side-effects to such memory locations.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Andrey Tarasevich@3:633/280.2 to All on Tue Jul 23 12:53:49 2024
    On 07/22/24 10:51 AM, testuseri2p wrote:
    I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.

    In simple words, if the variable(s) in the above expression have
    user-defined types and, consequently, the operators in the above
    expression are user-defined (as opposed to being built-in), then your
    above statement does not apply. You can end up with unspecified
    behavior, but not with undefined behavior.

    Which is why, once again, there's no specific answer to the original
    question without knowing more about the types of the variables involved.

    As for more formal words - see the adjacent answers.

    --
    Best regards,
    Andrey

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Tue Jul 23 13:40:37 2024
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    On 7/22/24 13:51, testuseri2p wrote:
    I'd say in simple words, if you alter a variable multiple times in one
    statement, you get UB.

    The correct (and admittedly more complicated) statement of the relevant
    rule is:
    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is undefined."

    The biggest difference between the exact rule and what you said is that
    two different updates to a variable may occur in the same statement, so
    long as they are sequenced relative to each other. Sub-expressions of an expression are sequenced before evaluation of the expression itself. In general, the sub-expressions of a expression are unsequenced, but there several exceptions: ||, &&, ?:, the comma operator.

    "Sub-expressions of an expression are sequenced before evaluation of the expression itself." isn't quite correct. What the C++ standard says is
    that "The value computations of the operands of an operator are
    sequenced before the value computation of the result of the operator."

    In `++f * ++f`, the values yielded by the two ++f subexpressions are
    determined before the "*" operator can be evaluated, but the side
    effects of incrementing f (twice) can happen any time before the end of
    the evaluation of the full expression.

    The full expression is `x *= ++f * ++f`. There are three side effects, modifications to x, f, and f, and they can happen in any order. (It's
    because the two modifications of f are unsequenced that the behavior is undefined.

    `x *= ++f * ++g` would be well defined, as long as there f and g are initialized and aren't any hidden games with any of x, f, and g being references to the same object. And the side effects on f and g could
    happen before or after the multiplication and assignment are evaluated.

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which no declaration exists - it is still undefined behavior to write code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us what it
    means.

    "A *variable* is introduced by the declaration of a reference other than
    a non-static data member or of an object. The variable’s name, if any, denotes the reference or object."

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Wed Jul 24 00:01:28 2024
    On 7/22/24 13:51, testuseri2p wrote:
    I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.

    The correct (and admittedly more complicated) statement of the relevant
    rule is:
    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is undefined."

    The biggest difference between the exact rule and what you said is that
    two different updates to a variable may occur in the same statement, so
    long as they are sequenced relative to each other. Sub-expressions of an expression are sequenced before evaluation of the expression itself. In general, the sub-expressions of a expression are unsequenced, but there
    several exceptions: ||, &&, ?:, the comma operator.

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which no declaration exists - it is still undefined behavior to write code that
    applies unsequence side-effects to such memory locations.


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Wed Jul 24 00:15:29 2024
    On 7/22/24 23:40, Keith Thompson wrote:
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    On 7/22/24 13:51, testuseri2p wrote:
    I'd say in simple words, if you alter a variable multiple times in one
    statement, you get UB.

    The correct (and admittedly more complicated) statement of the relevant
    rule is:
    "If a side effect on a memory location (6.7.1) is unsequenced relative
    to either another side effect on the same memory location or a value
    computation using the value of any object in the same memory location,
    and they are not potentially concurrent (6.9.2), the behavior is
    undefined."

    The biggest difference between the exact rule and what you said is that
    two different updates to a variable may occur in the same statement, so
    long as they are sequenced relative to each other. Sub-expressions of an
    expression are sequenced before evaluation of the expression itself. In
    general, the sub-expressions of a expression are unsequenced, but there
    several exceptions: ||, &&, ?:, the comma operator.

    "Sub-expressions of an expression are sequenced before evaluation of the expression itself." isn't quite correct. What the C++ standard says is
    that "The value computations of the operands of an operator are
    sequenced before the value computation of the result of the operator."

    Yes, you're right. I should have checked before posting. Since this rule
    is about side-effects, not value computations, the sequencing provided
    by that clause is irrelevant to what I was talking about. I remember
    thinking that it didn't sound right, and I would probably have realized
    my mistake if I'd taken a few more minutes to think about it, but I was
    in a hurry to get a pair of 9-year olds to bed.

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which no
    declaration exists - it is still undefined behavior to write code that
    applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us what it means.

    "A *variable* is introduced by the declaration of a reference other than
    a non-static data member or of an object. The variable’s name, if any, denotes the reference or object."

    That's the relevant clause. A declaration always declares an identifier
    to be the name of the thing declared. Therefore, a memory location that
    doesn't have a declared name doesn't qualify as a C variable. However,
    such memory locations are still subject to the above rule.



    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Tim Rentsch@3:633/280.2 to All on Wed Jul 24 00:28:44 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    [...]
    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Tim Rentsch@3:633/280.2 to All on Wed Jul 24 00:32:56 2024
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    On 7/22/24 13:51, testuseri2p wrote:

    I'd say in simple words, if you alter a variable multiple times in
    one statement, you get UB.

    The correct (and admittedly more complicated) statement of the
    relevant rule is:

    "If a side effect on a memory location (6.7.1) is unsequenced
    relative to either another side effect on the same memory location
    or a value computation using the value of any object in the same
    memory location, and they are not potentially concurrent (6.9.2),
    the behavior is undefined."

    The biggest difference between the exact rule and what you said is
    that two different updates to a variable may occur in the same
    statement, so long as they are sequenced relative to each other. Sub-expressions of an expression are sequenced before evaluation of
    the expression itself. In general, the sub-expressions of a
    expression are unsequenced, but there several exceptions: ||, &&,
    ?:, the comma operator.

    Don't forget << (and also >>?).

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write code
    that applies unsequence side-effects to such memory locations.

    The original statement most likely meant "variable" as a stand-in
    for "object".

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Wed Jul 24 07:42:07 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    [...]
    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with what
    the standard says. Under the latter interpretation, the "variable" has
    a name, and that name denotes an object, but the variable is not the
    object.

    Given the above declaration, is the introduced variable an object? If
    so, or if not, how does your answer follow from what the standard says?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Wed Jul 24 08:05:43 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    [...]
    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with what
    the standard says. Under the latter interpretation, the "variable" has
    a name, and that name denotes an object, but the variable is not the
    object.

    Given the above declaration, is the introduced variable an object? If
    so, or if not, how does your answer follow from what the standard says?

    On further thought, I think the intent has to be that a variable is not
    an object. A variable is introduced by a declaration, and a declaration
    is not necessarily a definition.

    For example, given:

    int var = 42;
    int main() {
    extern int var;
    }

    There are two declarations for "var"; only the first is a definition.
    If I understand correctly, each of these declarations introduces a
    variable. So apparently there are two variables with the name "var",
    but only one object. Or is there just one variable that's "introduced"
    twice?

    But the following paragraph says:

    A *local entity* is a variable with automatic storage duration
    (6.7.5.4), a structured binding (9.6) whose corresponding variable
    is such an entity, or the *this object (7.5.3).

    Storage duration is an attribute of objects. If a variable can have
    automatic storage duration, then apparently a variable is an object.

    Informally, I think of a "variable" as an object whose name is an
    identifer. Given `int foo[10];`, foo would be a variable, but foo[1]
    would not.

    Perhaps I'm missing something obvious, but I don't know what.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)
  • From Tim Rentsch@3:633/280.2 to All on Sun Aug 11 23:11:24 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    [...]

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with
    what the standard says. Under the latter interpretation, the
    "variable" has a name, and that name denotes an object, but the
    variable is not the object.

    Given the above declaration, is the introduced variable an object?
    If so, or if not, how does your answer follow from what the standard
    says?

    Even moreso than the C standard, the C++ standard needs to be read holistically. That may be a damning commentary on the quality of
    writing in the C++ standard, but I think it matches the reality.

    Given that, when confronted with a question like the ones you ask
    about the term "variable", a natural course of action to find
    answers to these questions might be to open the C++ standard in
    a PDF viewer, and use the viewer's search facility to look at
    places where the term in question is used. The more of those that
    can be looked at, the more likely it is that one will be able to
    discern answers to such questions. That's probably what I would
    do if I felt I needed a better understanding of, for example, what
    the term "variable" is supposed to mean.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Tim Rentsch@3:633/280.2 to All on Sun Aug 11 23:22:26 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    [...]

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with what
    the standard says. Under the latter interpretation, the "variable" has
    a name, and that name denotes an object, but the variable is not the
    object.

    Given the above declaration, is the introduced variable an object? If
    so, or if not, how does your answer follow from what the standard says?

    [...]

    But the following paragraph says:

    A *local entity* is a variable with automatic storage duration
    (6.7.5.4), a structured binding (9.6) whose corresponding variable
    is such an entity, or the *this object (7.5.3).

    Storage duration is an attribute of objects. If a variable can have automatic storage duration, then apparently a variable is an object.

    It seems clear that the quoted sentence is meant to be read as

    A *local entity* is a variable [associated with an object that
    has] automatic storage duration, [etc].

    I'm not sure if C++ references also have storage durations, in which
    case the word "object" in that sentence might need to be replaced with
    "object or reference". The key point though is that the property of
    having automatic storage duration is meant to be associated with the
    affiliated object or reference rather than with the variable itself.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Chris Ahlstrom@3:633/280.2 to All on Sun Aug 11 23:25:27 2024
    Tim Rentsch wrote this copyrighted missive and expects royalties:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:

    [...]

    A minor detail is that a variable must be declared, whereas memory
    locations can, for instance, be part of allocated memory for which
    no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations.

    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with
    what the standard says. Under the latter interpretation, the
    "variable" has a name, and that name denotes an object, but the
    variable is not the object.

    Given the above declaration, is the introduced variable an object?
    If so, or if not, how does your answer follow from what the standard
    says?

    Even moreso than the C standard, the C++ standard needs to be read holistically. That may be a damning commentary on the quality of
    writing in the C++ standard, but I think it matches the reality.

    Given that, when confronted with a question like the ones you ask
    about the term "variable", a natural course of action to find
    answers to these questions might be to open the C++ standard in
    a PDF viewer, and use the viewer's search facility to look at
    places where the term in question is used. The more of those that
    can be looked at, the more likely it is that one will be able to
    discern answers to such questions. That's probably what I would
    do if I felt I needed a better understanding of, for example, what
    the term "variable" is supposed to mean.

    This one gives me a headache:

    https://en.cppreference.com/w/cpp/language/value_category#:~:text=The%20expressions%20that%20have%20identity,and%20xvalues%20are%20rvalue%20expressions.

    Value categories

    Each C++ expression (an operator with its operands, a literal, a variable
    name, etc.) is characterized by two independent properties: a type and a
    value category. Each expression has some non-reference type, and each
    expression belongs to exactly one of the three primary value categories:
    prvalue, xvalue, and lvalue.

    Not to mention rvalue and glvalue.

    --
    Things past redress and now with me past care.
    -- William Shakespeare, "Richard II"

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None (3:633/280.2@fidonet)
  • From James Kuyper@3:633/280.2 to All on Mon Aug 12 04:17:17 2024
    Tim Rentsch wrote this copyrighted missive and expects royalties:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    ....
    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name,
    if any, denotes the reference or object."

    [That's 6.1p6]

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with
    what the standard says. Under the latter interpretation, the
    "variable" has a name, and that name denotes an object, but the
    variable is not the object.

    Given the above declaration, is the introduced variable an object?
    If so, or if not, how does your answer follow from what the standard
    says?

    Even moreso than the C standard, the C++ standard needs to be read holistically. That may be a damning commentary on the quality of
    writing in the C++ standard, but I think it matches the reality.

    Given that, when confronted with a question like the ones you ask
    about the term "variable", a natural course of action to find
    answers to these questions might be to open the C++ standard in
    a PDF viewer, and use the viewer's search facility to look at
    places where the term in question is used. The more of those that
    can be looked at, the more likely it is that one will be able to
    discern answers to such questions. That's probably what I would
    do if I felt I needed a better understanding of, for example, what
    the term "variable" is supposed to mean.

    It should not be necessary to do that. In 6.1p6, the word "variable" is italicized, an ISO convention identifying the sentence in which it
    occurs as the official definition of the term. As such, it is supposed
    to be sufficient to answer that question; there should be no need to
    infer the intended meaning by reading all of the uses of that term in
    the document.
    I agree, that counts as a damning statement about the quality of writing
    of at least that part of the standard.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: A noiseless patient Spider (3:633/280.2@fidonet)
  • From Keith Thompson@3:633/280.2 to All on Mon Aug 12 07:09:41 2024
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    [...]

    A minor detail is that a variable must be declared, whereas memory >>>>>> locations can, for instance, be part of allocated memory for which >>>>>> no declaration exists - it is still undefined behavior to write
    code that applies unsequence side-effects to such memory locations. >>>>>
    Digression: I'm not even sure what "variable" means in C++. The
    standard defines the term, but not in a way that really tells us
    what it means.

    "A *variable* is introduced by the declaration of a reference other
    than a non-static data member or of an object. The variable's name, >>>>> if any, denotes the reference or object."

    What part do you find confusing or hard to understand?

    The missing part that should tell us what a variable *is*.

    It says that certain declarations "introduce" a variable. That's a
    statement about variables, but it doesn't say what a variable is.

    Given:

    int n;

    we know that the declaration introduces a variable. Is the object
    itself a "variable"? That's the obvious meaning, and it's consistent
    with what the standard says. Or is a "variable" some kind of logical
    binding between an object and a name? That's also consistent with what
    the standard says. Under the latter interpretation, the "variable" has
    a name, and that name denotes an object, but the variable is not the
    object.

    Given the above declaration, is the introduced variable an object? If
    so, or if not, how does your answer follow from what the standard says?

    [...]

    But the following paragraph says:

    A *local entity* is a variable with automatic storage duration
    (6.7.5.4), a structured binding (9.6) whose corresponding variable
    is such an entity, or the *this object (7.5.3).

    Storage duration is an attribute of objects. If a variable can have
    automatic storage duration, then apparently a variable is an object.

    It seems clear that the quoted sentence is meant to be read as

    A *local entity* is a variable [associated with an object that
    has] automatic storage duration, [etc].

    It seems clear to you. It's not clear to me. If the only way to
    understand a passage is to assume it includes extra words, it is at best
    poorly written -- and I can't be sure that any assumptions about what it *really* means are correct.

    I'm not sure if C++ references also have storage durations, in which
    case the word "object" in that sentence might need to be replaced with "object or reference". The key point though is that the property of
    having automatic storage duration is meant to be associated with the affiliated object or reference rather than with the variable itself.

    Perhaps so, but that still doesn't tell me what a "variable" is.

    Apparently a "variable" is something *associated with* an object. But
    what is it, and how is the concept useful when we already have the
    concept of an "object"?

    I tried following your advice and searchin for uses of "variable" in the
    C++ standard (which, as James Kuyper pointed out, should not be
    necessary to understand the definition). It was not helpful. For
    example, "Variables with static storage duration are initialized as a consequence of program initiation.". So a variable is a thing that can
    have a storage duration and be initialized? And it's not an object?

    I get the impression (quite possibly mistaken) that the authors of the
    standard implicitly assume in some places that a variable is an object,
    and in other places that it's something else.

    The most obvious meaning is that a "variable" is an object that has a
    name introduced by a declaration. (I'll gloss over the question of
    whether something that's const-qualified is a "variable", but I'm
    willing to accept that "variable" doesn't have to mean that something
    can vary.) But that's not what the standard says.

    I'll note that the C standard does not define or use the term "variable" (though it does use the word in its non-tecnical sense). Instead it
    refers to "objects". Perhaps C++ could have done the same.

    If I were to ask you "What is a variable in C++?", could you give a
    clear answer? What would that answer be? Is a variable an object or
    is it not?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: None to speak of (3:633/280.2@fidonet)