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

    From Marcel Mueller@21:1/5 to All on Thu May 23 19:11:19 2024
    Am 23.05.24 um 16:14 schrieb Bonita Montero:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    AFAIK depending on the sequence of execution for arguments (of operator
    *) is UB.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Marcel Mueller on Thu May 23 19:08:43 2024
    On 5/23/24 13:11, Marcel Mueller wrote:
    Am 23.05.24 um 16:14 schrieb Bonita Montero:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    AFAIK depending on the sequence of execution for arguments (of operator
    *) is UB.

    You're close to the right idea, but you've got the wording wrong. When
    support for threading was added to C++ many years ago, they introduced
    new jargon to make it possible to talk more precisely about which events
    were, or were not, guaranteed to be sequenced before other events. That
    jargon allowed them to more precisely specify what you need to do when
    writing multi-threaded code, in order to avoid problems.

    The key statement is:

    "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 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 has undefined behavior.

    Before support for multi-threading was added to the language, the
    behavior was undefined, but the clause that said so was much harder to understand, and was frequently the subject of arguments about how it
    applied. It takes time to understand the new jargon, but once you do,
    the relevant rules are much easier to understand.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stuart Redmann@21:1/5 to James Kuyper on Sat May 25 08:50:58 2024
    James Kuyper <[email protected]> wrote:
    On 5/23/24 13:11, Marcel Mueller wrote:
    Am 23.05.24 um 16:14 schrieb Bonita Montero:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    AFAIK depending on the sequence of execution for arguments (of operator
    *) is UB.

    You're close to the right idea, but you've got the wording wrong. When support for threading was added to C++ many years ago, they introduced
    new jargon to make it possible to talk more precisely about which events were, or were not, guaranteed to be sequenced before other events. That jargon allowed them to more precisely specify what you need to do when writing multi-threaded code, in order to avoid problems.

    The key statement is:

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

    Do I remember correctly that operator<< is one of the operators that
    explicitly is mentioned to introduce sequence points, so

    std::cout << ++f << ++f;

    is legal, but ++f * ++f is UB?

    TIA
    Stuart

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Sat May 25 10:00:10 2024
    Am 25.05.24 um 08:50 schrieb Stuart Redmann:
    Do I remember correctly that operator<< is one of the operators that explicitly is mentioned to introduce sequence points, so

    std::cout << ++f << ++f;

    is legal, but ++f * ++f is UB?

    AFAIK only constexpr functions can become part of a single expression.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Sam@21:1/5 to Stuart Redmann on Sat May 25 06:39:32 2024
    Stuart Redmann writes:

    Do I remember correctly that operator<< is one of the operators that explicitly is mentioned to introduce sequence points, so

    std::cout << ++f << ++f;

    is legal, but ++f * ++f is UB?

    Yes, but only as of C++17. Both are UB prior to C++17.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Stuart Redmann on Sat May 25 12:31:46 2024
    On 25/05/2024 08:50, Stuart Redmann wrote:
    James Kuyper <[email protected]> wrote:
    On 5/23/24 13:11, Marcel Mueller wrote:
    Am 23.05.24 um 16:14 schrieb Bonita Montero:
    Is "x *= ++f * ++f" a valid statement ?
    Or is there implementation defined behaviour ?

    AFAIK depending on the sequence of execution for arguments (of operator
    *) is UB.

    You're close to the right idea, but you've got the wording wrong. When
    support for threading was added to C++ many years ago, they introduced
    new jargon to make it possible to talk more precisely about which events
    were, or were not, guaranteed to be sequenced before other events. That
    jargon allowed them to more precisely specify what you need to do when
    writing multi-threaded code, in order to avoid problems.

    The key statement is:

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

    Do I remember correctly that operator<< is one of the operators that explicitly is mentioned to introduce sequence points, so

    std::cout << ++f << ++f;

    is legal, but ++f * ++f is UB?

    TIA
    Stuart


    I don't believe the C++ standards use the term "sequence point", at
    least not as found in the C standards. But it is correct that in C++17,
    for E1 << E2, the evaluation of E1 is sequenced before the evaluation of
    E2. (They are unsequenced in C and earlier C++ standards.)

    So I believe you are correct that for C++17 onwards, "std::cout << ++f
    << ++f;" has fully defined behaviour while "std::cout << ++f * ++f;" has undefined behaviour.

    (But it's worth noting that this is for C++17 onwards - many people use
    older C++ standards.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to Bonita Montero on Tue Jun 18 18: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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Damon@21:1/5 to Bonita Montero on Tue Jun 18 22: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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Damon@21:1/5 to olcott on Sun Jun 23 07: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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Damon@21:1/5 to olcott on Sun Jun 23 14: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".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Damon@21:1/5 to olcott on Sun Jun 23 16: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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Richard Damon on Mon Jun 24 09: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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to All on Mon Jul 22 21: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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to All on Mon Jul 22 19: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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Tue Jul 23 07:28:44 2024
    Keith Thompson <[email protected]> writes:

    James Kuyper <[email protected]> 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?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to James Kuyper on Tue Jul 23 07:32:56 2024
    James Kuyper <[email protected]> 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".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Keith Thompson on Tue Jul 23 10:15:29 2024
    On 7/22/24 23:40, Keith Thompson wrote:
    James Kuyper <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Sun Aug 11 06:11:24 2024
    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    James Kuyper <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Ahlstrom@21:1/5 to Tim Rentsch on Sun Aug 11 09:25:27 2024
    Tim Rentsch wrote this copyrighted missive and expects royalties:

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    James Kuyper <[email protected]> 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"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Sun Aug 11 06:22:26 2024
    Keith Thompson <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    James Kuyper <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Tim Rentsch on Sun Aug 11 14:17:17 2024
    Tim Rentsch wrote this copyrighted missive and expects royalties:

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)