Is "x *= ++f * ++f" a valid statement ?
Or is there implementation defined behaviour ?
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.
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?
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?
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
Is "x *= ++f * ++f" a valid statement ?
Or is there implementation defined behaviour ?
Is "x *= ++f * ++f" a valid statement ?
Or is there implementation defined behaviour ?
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.
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.
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?
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.
I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.
I'd say in simple words, if you alter a variable multiple times in one statement, you get UB.
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."
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.
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."
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."
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?
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.
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.
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."
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.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (3 / 13) |
| Uptime: | 19:15:48 |
| Calls: | 12,104 |
| Calls today: | 4 |
| Files: | 15,004 |
| Messages: | 6,518,087 |