I know that writing something like
++a = a++;
Is not only unreadable but also violates the c/c++ sequence points.
Where do these limitations come from? How can one see those 'problems' before finding them as bugs?
I know that writing something like
++a = a++;
Is not only unreadable but also violates the c/c++ sequence points.
Where do these limitations come from? How can one see those 'problems' before finding them as bugs?
Basically there is a C++03 sequence point between each statement. For more information see the SO C++ FAQ. For even more information do consult the C++ standard, and keep in mind that in the C++11 standard sequence points were replaced with sequenced before and sequenced after relations.
To avoid problems, simply don't try to be too clever about doing a lot in each expression.
Don't try to do the compiler's job: leave that to the compiler. Your job is to write code that other humans can easily understand, i.e. clear code. Multiple updates and needless use of operators with side effects is not compatible with that.
Tip: sprinkle const
just about everywhere possible.
That constrains the possible state changes that a reader must take into account.
They come from the C or C++ standard, which effectively lists sequence points.1 In a few simple cases, your compiler may be able to warn you that you're invoking undefined behaviour, but not in the general case.
However, you're generally only ever violating sequence-point requirements if you're writing "interesting" code such as your example. The language standard could impose particular constraints on code such as this (which is what languages such as Java do), but there's not a great deal of upside, and the potential downside of preventing certain types of optimisation.
How can one see those 'problems' before finding them as bugs?
Compile your program with strictest level and enable the settings for all warnings to be pointed out as errors. Most mainstream compilers do point out Undefined Behavior errors due to sequence points.
With gcc you can use:
-Wsequence-point
which shall point out sequence point problems. Note that it is enabled by default if you use -Wall
.
Of course, the best way is to try and write more readable code which avoids sequence point mis-adventures.
-Wall
enables it by default, as I already mentioned. –
Histoid Where do these limitations come from? How can one see those 'problems' before finding them as bugs?
They come from ambiguity in (or freedom to modify) the order of operations during execution.
For your example:
++a = a++;
the language leaves undefined whether the pre-increment on the lvalue should occur before or after the post-increment on the rvalue. Adding a constraint here would incur significant costs; what is the general benefit? What is the clear, obvious way that this example code 'should' behave?
To boost performance, the order of operations in a program may be changed (within strict limits) by the compiler and/or the processor.
Overly constraining execution order would:
Let's look at constraining the order of execution for a different code sample:
a = b++ + ++c - --d - e--;
Suppose that only a limited number of registers are available, and that some of the variables ('d' and 'e') are in registers and some are not. Strictly constraining execution order (let's say left to right) might require:
While if allowed to e.g. process 'd' and 'e' first and to increment 'b' at a slightly later time, the compiler may be able to significantly reduce the number of steps and boost performance.
a
is an lvalue in both cases in ++a = a++
, it should not say "post-increment on the rvalue" since in fact a post-increment can only occur on an lvalue (for built-in types). –
Queensland © 2022 - 2025 — McMap. All rights reserved.
error: operation on 'a' may be undefined [-Werror=sequence-point]
- Ah, thank you, handy compiler. – Juglandaceous-Werror -Wall -Wextra -ansi -pedantic
– Chantellechanter