Rectangle 27 432

try:
  thevariable
except NameError:
  print "well, it WASN'T defined after all!"
else:
  print "sure, it was defined."

@Aaron: There are many cases when you don't know whether variable is defined. You can refactor code to avoid this in many, but not all cases. Alex's solution is correct and it the best when refactoing is not possible for some reasons. There is not much information in the question, so I believe only person asked it can select the best way to handle his case.

@Aaron, "should" is a 4-letter word -- e.g. no driver "should" ever exceed the speed limit, but that doesn't mean you don't take all proper and needed precautions against those who nevertheless do. Maintaining fragile, undertested legacy code with somewhat-broken design that you inherited from somebody else is a fact of life, and those who can only think of big-bang rewriting from scratch rather than cautiously and incrementally need to re-read Joel's 9-years-old essay joelonsoftware.com/articles/fog0000000069.html .

@S.Lott People use it to maintain backwards compatibility. Search for NameError in Python 3.1 source code. There are many instances where "try: var_name except NameError: something_else" is used. Here are a couple of place where it is used: CSV (svn.python.org/projects/python/trunk/Lib/csv.py) library and in the ElementTree library (svn.python.org/projects/python/trunk/Lib/xml/etree/).

This debate is much more interesting that the answer itself, which by the way is 100% correct and let you handle poor legacy code elegantly.

@einpoklum, Python uses exception StopIteration within just about every for statement -- that's how an iterator lets it known that it's all done. And of course, it is far from "an exceptional case" for iteration to be done -- indeed, one expects most iterations to terminate. Thus, obviously, your opinions on how exceptions "should" be used are not correctly applicable to Python (other languages have different pragmatics and the question cannot be properly treated as "language agnostic" as in the Q you point to).

Determine if variable is defined in Python - Stack Overflow

python variables defined
Rectangle 27 432

try:
  thevariable
except NameError:
  print "well, it WASN'T defined after all!"
else:
  print "sure, it was defined."

@Aaron: There are many cases when you don't know whether variable is defined. You can refactor code to avoid this in many, but not all cases. Alex's solution is correct and it the best when refactoing is not possible for some reasons. There is not much information in the question, so I believe only person asked it can select the best way to handle his case.

@Aaron, "should" is a 4-letter word -- e.g. no driver "should" ever exceed the speed limit, but that doesn't mean you don't take all proper and needed precautions against those who nevertheless do. Maintaining fragile, undertested legacy code with somewhat-broken design that you inherited from somebody else is a fact of life, and those who can only think of big-bang rewriting from scratch rather than cautiously and incrementally need to re-read Joel's 9-years-old essay joelonsoftware.com/articles/fog0000000069.html .

@S.Lott People use it to maintain backwards compatibility. Search for NameError in Python 3.1 source code. There are many instances where "try: var_name except NameError: something_else" is used. Here are a couple of place where it is used: CSV (svn.python.org/projects/python/trunk/Lib/csv.py) library and in the ElementTree library (svn.python.org/projects/python/trunk/Lib/xml/etree/).

This debate is much more interesting that the answer itself, which by the way is 100% correct and let you handle poor legacy code elegantly.

@einpoklum, Python uses exception StopIteration within just about every for statement -- that's how an iterator lets it known that it's all done. And of course, it is far from "an exceptional case" for iteration to be done -- indeed, one expects most iterations to terminate. Thus, obviously, your opinions on how exceptions "should" be used are not correctly applicable to Python (other languages have different pragmatics and the question cannot be properly treated as "language agnostic" as in the Q you point to).

Determine if variable is defined in Python - Stack Overflow

python variables defined
Rectangle 27 425

try:
  thevariable
except NameError:
  print "well, it WASN'T defined after all!"
else:
  print "sure, it was defined."

@Aaron: There are many cases when you don't know whether variable is defined. You can refactor code to avoid this in many, but not all cases. Alex's solution is correct and it the best when refactoing is not possible for some reasons. There is not much information in the question, so I believe only person asked it can select the best way to handle his case.

@Aaron, "should" is a 4-letter word -- e.g. no driver "should" ever exceed the speed limit, but that doesn't mean you don't take all proper and needed precautions against those who nevertheless do. Maintaining fragile, undertested legacy code with somewhat-broken design that you inherited from somebody else is a fact of life, and those who can only think of big-bang rewriting from scratch rather than cautiously and incrementally need to re-read Joel's 9-years-old essay joelonsoftware.com/articles/fog0000000069.html .

@S.Lott People use it to maintain backwards compatibility. Search for NameError in Python 3.1 source code. There are many instances where "try: var_name except NameError: something_else" is used. Here are a couple of place where it is used: CSV (svn.python.org/projects/python/trunk/Lib/csv.py) library and in the ElementTree library (svn.python.org/projects/python/trunk/Lib/xml/etree/).

This debate is much more interesting that the answer itself, which by the way is 100% correct and let you handle poor legacy code elegantly.

Exceptions should be reserved for exceptional cases, not for use as the bastard brother of 'if' :-(

Determine if variable is defined in Python - Stack Overflow

python variables defined
Rectangle 27 200

The operations are well defined according to the draft C++ standard.

5.9

The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t. The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool

and bools are arithematic types from 3.9.1 Fundamental types

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.

and

Integral and floating types are collectively called arithmetic types.

and true and false are boolean literals from 2.14.6 Boolean literals:

boolean-literal:
    false
    true

Going back to section 5.9 to see the mechanics of the relational operators further, it says:

The usual arithmetic conversions are performed on operands of arithmetic or enumeration type.

Otherwise, the integral promotions (4.5) shall be performed on both operands

4.5

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

false < false
false < true
true < false
true < true
0 < 0
0 < 1
1 < 0
1 < 1

Nice, that's about as explicit as any answer could possibly be, while still easy to read. A nit: I think you bolded the wrong "type": "The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t." Adding parentheses for clarity gives ((arithmetic, enumeration, or pointer) type) or (type std::nullptr_t).

@chris I am not super familiar with that section so I would have to think about it but I don't think the answer changes from what I can see.

Yeah, the promotion is the first thing to happen either way.

c++ - Is the operation "false < true" well defined? - Stack Overflow

c++ boolean language-lawyer comparison-operators
Rectangle 27 200

The operations are well defined according to the draft C++ standard.

5.9

The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t. The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool

and bools are arithematic types from 3.9.1 Fundamental types

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.

and

Integral and floating types are collectively called arithmetic types.

and true and false are boolean literals from 2.14.6 Boolean literals:

boolean-literal:
    false
    true

Going back to section 5.9 to see the mechanics of the relational operators further, it says:

The usual arithmetic conversions are performed on operands of arithmetic or enumeration type.

Otherwise, the integral promotions (4.5) shall be performed on both operands

4.5

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

false < false
false < true
true < false
true < true
0 < 0
0 < 1
1 < 0
1 < 1

Nice, that's about as explicit as any answer could possibly be, while still easy to read. A nit: I think you bolded the wrong "type": "The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t." Adding parentheses for clarity gives ((arithmetic, enumeration, or pointer) type) or (type std::nullptr_t).

@chris I am not super familiar with that section so I would have to think about it but I don't think the answer changes from what I can see.

Yeah, the promotion is the first thing to happen either way.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

c++ - Is the operation "false < true" well defined? - Stack Overflow

c++ boolean language-lawyer comparison-operators
Rectangle 27 63

Boolean values are subject to the usual integer promotions, with false defined as 0 and true defined as 1. That makes all the comparisons well defined.

...and relational operators are specified to perform the usual arithmetic conversions (which includes integer promotions) on operands of arithmetic or enumeration type.

I like that this answer is shorter than Shafik's, but I think the key point that false is defined as 0 and true is defined as 1 in the standard (rather than just by common practice) needs evidence to back it up.

@KRyan what, you're not going to take my word for it? :) Before there was a bool type, before there was even C++, the result of a boolean operation was defined as 0 for false and 1 for true. I wouldn't be surprised if you can find it in K+R.

@KRyan I can't go back quite as far as K+R, but I dug out my copy of the 1990 ANSI C Standard. Section 6.3.8 says "Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int."

The biggest problem IIRC was that in K&R, enum bool { false = 0, true = 1} was legal but didn't define an operator<.

c++ - Is the operation "false < true" well defined? - Stack Overflow

c++ boolean language-lawyer comparison-operators
Rectangle 27 63

Boolean values are subject to the usual integer promotions, with false defined as 0 and true defined as 1. That makes all the comparisons well defined.

...and relational operators are specified to perform the usual arithmetic conversions (which includes integer promotions) on operands of arithmetic or enumeration type.

I like that this answer is shorter than Shafik's, but I think the key point that false is defined as 0 and true is defined as 1 in the standard (rather than just by common practice) needs evidence to back it up.

@KRyan what, you're not going to take my word for it? :) Before there was a bool type, before there was even C++, the result of a boolean operation was defined as 0 for false and 1 for true. I wouldn't be surprised if you can find it in K+R.

@KRyan I can't go back quite as far as K+R, but I dug out my copy of the 1990 ANSI C Standard. Section 6.3.8 says "Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int."

The biggest problem IIRC was that in K&R, enum bool { false = 0, true = 1} was legal but didn't define an operator<.

c++ - Is the operation "false < true" well defined? - Stack Overflow

c++ boolean language-lawyer comparison-operators
Rectangle 27 18

Yes, it is well defined. Built-in operator[] is defined in terms of pointer arithmetic. This:

p[N]

where p is a pointer and N is an integer, is equivalent to this:

*(p + N)

An interesting upshot of this is that this:

N[p]

The latter example assumes the use of the built-in subscript operator.

@black: So does the former. And I mentioned that at the top of my post.

Not sure if I'd call it "up"-shot. ;-p Is N[p] ever useful?

c++ - Is negative index for operator[] well defined? - Stack Overflow

c++ operator-overloading language-lawyer
Rectangle 27 10

Yes, it is well-defined, as is any other unary type trait.

Each of these templates shall be a UnaryTypeTrait (20.10.1) with a BaseCharacteristic of true_type if the corresponding condition is true, otherwise false_type.

A UnaryTypeTrait describes a property of a type. It shall be a class template that takes one template type argument and, optionally, additional arguments that help define the property being described. It shall be DefaultConstructible, CopyConstructible, and publicly and unambiguously derived, directly or indirectly, from its BaseCharacteristic, which is a specialization of the template integral_constant (20.10.3), with the arguments to the template integral_constant determined by the requirements for the particular property being described. The member names of the BaseCharacteristic shall not be hidden and shall be unambiguously available in the UnaryTypeTrait.

From this it follows that the construct std::is_unsigned<T>::value has to be well-defined for any type T, whether the concept of "signedness" makes sense for the type or not.

c++ - Is std::is_unsigned::value well defined? - Stack Overflow

c++ boolean language-lawyer c++14 unsigned
Rectangle 27 38

The behavior is well defined in C# and the evaluation order is:

  • Left side i is evaluated to the variable i
i==1
  • The assignment is executed, it sets i to 0. (now i==0)
i==0

In general you first create an expression tree. To evaluate it you evaluate first the left side, then the right side and finally the operation at the root. Do that recursively.

Ah! It makes sense. I'm silly :)

In Java you can occasionally observe the value 1 from a parallel thread if you make i volatile (in my test typically 65 times in 100 million iterations).

i = ++i should work fine as well.

@A-b i = ++i would result in i being 1 in the end. But I'm not sure what you mean by work fine, since this question has to specific purpose the code need to achieve.

The post -increment operator i++ operator is defined as incrementing i but returning the value it had before. The pre -increment operator ++i on the other hand returns the incremented value. i++ => temp=i;i=i+1;return temp; vs. ++i => i=i+1;return i;

c# - i = i++ doesn't increment i. Why? - Stack Overflow

c# increment
Rectangle 27 38

The behavior is well defined in C# and the evaluation order is:

  • Left side i is evaluated to the variable i
i==1
  • The assignment is executed, it sets i to 0. (now i==0)
i==0

In general you first create an expression tree. To evaluate it you evaluate first the left side, then the right side and finally the operation at the root. Do that recursively.

Ah! It makes sense. I'm silly :)

In Java you can occasionally observe the value 1 from a parallel thread if you make i volatile (in my test typically 65 times in 100 million iterations).

i = ++i should work fine as well.

@A-b i = ++i would result in i being 1 in the end. But I'm not sure what you mean by work fine, since this question has to specific purpose the code need to achieve.

The post -increment operator i++ operator is defined as incrementing i but returning the value it had before. The pre -increment operator ++i on the other hand returns the incremented value. i++ => temp=i;i=i+1;return temp; vs. ++i => i=i+1;return i;

c# - i = i++ doesn't increment i. Why? - Stack Overflow

c# increment
Rectangle 27 20

In C++11 the expression is well defined and will result in i == 20.

[expr.ass]/1

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

This means that the assignment i+=1 is sequenced before the value computation of the left hand side of (i+=10)+=10, which is in turn sequenced before the final assignment to i.

In C++03 the expression has undefined behavior, because it causes i to be modified twice with no intervening sequence point.

@PaulR: C++11 only. C++03 had no notion of "sequenced after", it used sequence points. And in fact, in C++03 it is undefined, because there's no intervening sequence point between the assignments.

Thanks - this should really be clarified in the answer then, as the question does not specify C++11.

@PaulR In C++98 the paragraph says "The result of the assignment operation is the value stored in the left operand after the assignment has taken place;" I'm not sure if that technically means there's a sequence point between assignments. At the very least I think this is under-specified in C++98.

... maybe it's worthy to mention that because the result of i+=10 is lvalue (i.e the "i" object itself) the modification of i cannot be treated as "independed" side effect (which is not sequenced with anything until final ";" )

c++11 - In which versions of the C++ standard does "(i+=10)+=10" have ...

c++ c++11 undefined-behavior language-lawyer c++03
Rectangle 27 547

I'll take the risk of stating the obvious: You call the function, if it's defined in the base class it's automatically available in the derived class (unless it's private).

If there is a function with the same signature in the derived class you can disambiguate it by adding the base class's name followed by two colons base_class::foo(...). You should note that unlike Java and C#, C++ does not have a keyword for "the base class" (super or base) since C++ supports multiple inheritance which may lead to ambiguity.

class left {
public:
    void foo();
};

class right {
public:
    void foo();
};

class bottom : public left, public right {
public:
    void foo()
    {
        //base::foo();// ambiguous
        left::foo();
        right::foo();

        // and when foo() is not called for 'this':
        bottom b;
        b.left::foo();  // calls b.foo() from 'left'
        b.right::foo();  // call b.foo() from 'right'
    }
};

Incidentally, you can't derive directly from the same class twice since there will be no way to refer to one of the base classes over the other.

class bottom : public left, public left { // Illegal
};

Why would you like to inherit from the same class twice ?

@bluesm: in classic OOP it makes no much sense, but in generic programming template<class A, class B> class C: public A, public B {}; can come to two types being the same for reasons depending on how your code is used (that makes A and B to be the same), may be two or three abstraction layer way from someone not aware of what you did.

I think it's useful to add, that this will call parent class method even if it is not implemented directly in the parent class, but is implemented in one of the parent classes in the inheritance chain.

On a sidenote, it made me mad when i tried to put this in a cpp file. I had 'using namespace std'. 'left' is defined somewhere in that namespace. The example wouldn't compile - drove me crazy :) . Then I changed 'left' to 'Left'. Great example by the way.

@Mathai And that is why you aren't supposed to use using namespace std.

c++ - How to call a parent class function from derived class function?...

c++ oop inheritance
Rectangle 27 8

No, the behavior of a for (;;) statement is well defined in C.

N1570, which is essentially identical to the offical 2011 ISO C standard, says, in section 6.8.5 paragraph 6:

An iteration statement whose controlling expression is not a constant expression, that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.

with two footnotes:

An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.

This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven.

The first footnote makes it clear that for (;;) is treated as if it had a constant controlling expression.

The point of the rule is to permit optimizations when the compiler can't prove that the loop terminates. But if the controlling expression is constant, the compiler can trivially prove that the loop does or does not terminate, so the additional permission isn't needed.

while(1);

@Mehrdad: IMHO it should, but the C++ standard doesn't exclude constant controlling expressions from its version of the rule.

Just to be sure to capture what all of this means: in C you can write a program where the logic is completely implemented with signal handlers and have the program sit in an infinite loop to wait for an event. This doesn't sound like a very clever implementation of something, but I agree that the language shouldn't prohibit this. In C++ this would be forbidden?

Is an (empty) infinite loop undefined behavior in C? - Stack Overflow

c infinite-loop undefined-behavior
Rectangle 27 10

It's not as well defined as you probably want it to be. Most of the relevant standardese from C++98 is in section 1.9, "Program Execution":

The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

Accessing an object designated by a volatile lvalue (3.10), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression might produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.

Once the execution of a function begins, no expressions from the calling function are evaluated until execution of the called function has completed.

When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects with type other than volatile sig_atomic_t are unspecified, and the value of any object not of volatile sig_atomic_t that is modified by the handler becomes undefined.

An instance of each object with automatic storage duration (3.7.2) is associated with each entry into its block. Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function or receipt of a signal).

The least requirements on a conforming implementation are:

So what that boils down to is:

Note that some known experts (Herb Sutter in particular) mention that a smart compiler can even treat a volatile variable as non volatile if it can demonstrate that it cannot be read externally: think on a variable declared volatile but not bound to a particular address, for which no pointers/references are passed to other code --example: an auto volatile variable, a conforming compiler can treat it as non-volatile.

I can see the logic, but that's leaning a bit too hard on the as-if rule if you ask me.

@DavidRodrguez-dribeas: Interesting notion, though the only case where I can imagine it as being relevant would be if a loop read or wrote a volatile variable some number of times; if such reads or writes have to be performed in sequence, no code after the loop could have any observable side-effects until the processor had performed the appropriate number of reads or writes. Such a thing might be better accomplished by having the standard specify a __SIDE_EFFECT() macro which would compel the compiler to do whatever was necessary to ensure that the code around it was executed in sequence.

c++ - What Rules does compiler have to follow when dealing with volati...

c++ memory compiler-construction rules volatile
Rectangle 27 21

Yes, it's well defined that it will call the Double overload. It couldn't call the Integer overload because there's no implicit conversion from double (which is the type of the conditional expression) to Integer.

Basically, there are two parts of this that are irrelevant:

  • That the method is being called from an overload
  • That the method argument is a conditional expression

So if you think about it as:

Double d = getSomeDoubleValueFromAnywhere();
add(d);

... which method would you expect to be called? Presumably the add(Double) method - so that's what is called in your situation too.

The tricky part is working out the type of the conditional expression - is it Double or double? I believe the rules (which are hard to follow, IMO) mean that it's Double, due to the use of a null literal (which is of the null type). If instead you had:

Double dv = null;
add(value == null ? dv : value.doubleValue());

... then the conditional expression type would be double, and you'd get a NullPointerException if value were ever null, because it would be trying to unbox the null value.

Thank you very much for the advice, and for fixing one of my very many bugs.

@FitzwilliamBennet-Darcy: My mistake - it wasn't a bug! (There are similar situations where it is though... I'm trying to remember the exact case now...)

@MadPhysicist: I'm still working on this, as it's not clear whether the type of the conditional expression is actually double or Double.

lub(null,Double)
lub

java - Does this function call itself or call the overload? - Stack Ov...

java method-overloading
Rectangle 27 21

Yes, it's well defined that it will call the Double overload. It couldn't call the Integer overload because there's no implicit conversion from double (which is the type of the conditional expression) to Integer.

Basically, there are two parts of this that are irrelevant:

  • That the method is being called from an overload
  • That the method argument is a conditional expression

So if you think about it as:

Double d = getSomeDoubleValueFromAnywhere();
add(d);

... which method would you expect to be called? Presumably the add(Double) method - so that's what is called in your situation too.

The tricky part is working out the type of the conditional expression - is it Double or double? I believe the rules (which are hard to follow, IMO) mean that it's Double, due to the use of a null literal (which is of the null type). If instead you had:

Double dv = null;
add(value == null ? dv : value.doubleValue());

... then the conditional expression type would be double, and you'd get a NullPointerException if value were ever null, because it would be trying to unbox the null value.

Thank you very much for the advice, and for fixing one of my very many bugs.

@FitzwilliamBennet-Darcy: My mistake - it wasn't a bug! (There are similar situations where it is though... I'm trying to remember the exact case now...)

@MadPhysicist: I'm still working on this, as it's not clear whether the type of the conditional expression is actually double or Double.

lub(null,Double)
lub

java - Does this function call itself or call the overload? - Stack Ov...

java method-overloading
Rectangle 27 34

tl;dr: The sequence of the modifications and reads performed in (i+=10)+=10 is well defined in both C++98 and C++11, however in C++98 this is not sufficient to make the behavior defined.

In C++98 multiple modifications to the same object without an intervening sequence-point results in undefined behavior, even when the order of those modifications is well specified. This expression does not contain any sequence points and so the fact that it consists of two modifications is sufficient to render its behavior undefined.

C++11 doesn't have sequence points and only requires that the modifications of an object be ordered with respect to each other and to reads of the same object to produce defined behavior.

Therefore the behavior is undefined in C++98 but well defined in C++11.

Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expression, and the order in which side effects take place, is unspecified.

The result of the assignment operation is the value stored in the left operand after the assignment has taken place; the result is an lvalue

So I believe the order is specified, however I don't see that that alone is enough to create a sequence point in the middle of an expression. And continuing on with the quote of [expr] 5 p4:

Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.

So even though the order is specified it appears to me that this is not sufficient for defined behavior in C++98.

C++11 does away sequence points for the much clearer idea of sequence-before and sequenced-after. The language from C++98 is replaced with

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...]

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

So while being ordered was not sufficient to make the behavior defined in C++98, C++11 has changed the requirement such that being ordered (i.e., sequenced) is sufficient.

(And it seems to me that the extra flexibility afforded by 'sequence before' and 'sequenced after' has lead to a much more clear, consistent, and well specified language.)

It seems unlikely to me that any C++98 implementation would actually do anything surprising when the sequence of operations is well specified even if that is insufficient to produce technically well defined behavior. As an example, the internal representation of this expression produced by Clang in C++98 mode has well defined behavior and does the expected thing.

"whereas in C++98 the value assigned to j is indeterminate but the behavior is not undefined" - this is incorrect. C++98 says that the previous value of "i" shall only be read to determine the value to be stored in a modification when there's no intervening sequence point. But in "(i+=1) + i", it is unspecified whether the "+ i" reads the previous or the next value of "i", so the consequence is there's undefined behavior.

@JohannesSchaub-litb Could you give me a citation so I can see it in the C++98 standard in context?

it is right after the text you quoted that ends with "... shall have its stored value modified at most once by the evaluation of an expression.".

@JohannesSchaub-litb I think you're probably right that the language was intended to mean that and that the requirement I had thought was new in C++11 isn't actually new. But the C++98 language definitely needed cleaning up because as written, "the prior value shall be accessed only to [...]," does not mean the same thing as "only the prior value shall be accessed."

@JohannesSchaub-litb However, if the intended meaning is "only the prior value shall be accessed" then does that mean that there's no requirement to access the prior value "only to determine the value to be stored?" I.e. am I allowed to access the prior value for other purposes?

c++11 - In which versions of the C++ standard does "(i+=10)+=10" have ...

c++ c++11 undefined-behavior language-lawyer c++03
Rectangle 27 10

When I first looked at this example I felt that the behaviour was well defined because this expression is actually short hand for a set of function calls.

cout << f1() << f2();

This is expanded to a sequence of function calls, where the kind of calls depend on the operators being members or non-members:

// Option 1:  Both are members
cout.operator<<(f1 ()).operator<< (f2 ());

// Option 2: Both are non members
operator<< ( operator<<(cout, f1 ()), f2 () );

// Option 3: First is a member, second non-member
operator<< ( cout.operator<<(f1 ()), f2 () );

// Option 4: First is a non-member, second is a member
cout.operator<<(f1 ()).operator<< (f2 ());

At the lowest level these will generate almost identical code so I will refer only to the first option from now.

There is a guarantee in the standard that the compiler must evaluate the arguments to each function call before the body of the function is entered. In this case, cout.operator<<(f1()) must be evaluated before operator<<(f2()) is, since the result of cout.operator<<(f1()) is required to call the other operator.

The unspecified behaviour kicks in because although the calls to the operators must be ordered there is no such requirement on their arguments. Therefore, the resulting order can be one of:

f2()
f1()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
f1()
f2()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
f1()
cout.operator<<(f1())
f2()
cout.operator<<(f1()).operator<<(f2());

Nice :) I was about to write something similar, but it took me a while to check what exactly guarantees that the various operator<< calls are done in sequence. As you stated it makes sense to me, since then the implied object argument is just seen as a normal function argument which is evaluated before the function-entry sequence point. I thought that argument just existed for the purpose of overloading, but it seems that it has importance for this side-effect games too. +1 :)

gcc - C++ Output evaluation order with embedded function calls - Stack...

c++ gcc mingw
Rectangle 27 20

It is well defined behavior. In C11 a new clause 6.8.5 ad 6 has been added

An iteration statement whose controlling expression is not a constant expression,156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)

Since the controlling expression of your loop is a constant, the compiler may not assume the loop terminates. This is intended for reactive programs that should run forever, like an operating system.

However for the following loop the behavior is unclear

a = 1; while(a);

In effect a compiler may or may not remove this loop, resulting in a program that may terminate or may not terminate. That is not really undefined, as it is not allowed to erase your hard disk, but it is a construction to avoid.

There is however another snag, consider the following code:

a = 1; while(a) while(1);

Now since the compiler may assume the outer loop terminates, the inner loop should also terminate, how else could the outer loop terminate. So if you have a really smart compiler then a while(1); loop that should not terminate has to have such non-terminating loops around it all the way up to main. If you really want the infinite loop, you'd better read or write some volatile variable in it.

Why this clause is not practical

It is very unlikely our compiler company is ever going to make use of this clause, mainly because it is a very syntactical property. In the intermediate representation (IR), the difference between the constant and the variable in the above examples is easily lost through constant propagation.

The intention of the clause is to allow compiler writers to apply desirable transformations like the following. Consider a not so uncommon loop:

int f(unsigned int n, int *a)
{       unsigned int i;
        int s;

        s = 0;
        for (i = 0; i < n-9; i++)
        {
                s += a[i+10];
        }
        return s;
}

Without clause 6.8.5 ad 6 this is not possible, because if n equals UINT_MAX, the loop may not terminate. Nevertheless it is pretty clear to a human that this is not the intention of the writer of this code. Clause 6.8.5 ad 6 now allows this transformation. However the way this is achieved is not very practical for a compiler writer as the syntactical requirement of an infinite loop is hard to maintain on the IR.

Note that it is essential that n and i are unsigned as overflow on signed int gives undefined behavior and thus the transformation can be justified for this reason. Efficient code however benefits from using unsigned, apart from the bigger positive range.

Our approach would be that the code writer has to express his intention by for example inserting an assert(n < UINT_MAX) before the loop or some Frama-C like guarantee. This way the compiler can "prove" termination and doesn't have to rely on clause 6.8.5 ad 6.

P.S: I'm looking at a draft of April 12, 2011 as paxdiablo is clearly looking at a different version, maybe his version is newer. In his quote the element of constant expression is not mentioned.

I'm looking at n1570, too, and I assure you that paxdiablo's quote is there, at the end of the page numbered 150 (168 in Adobe Reader page numbers)...

@undefinedbehaviour I just downloaded n1570 and it still has the version in my quote of the clause, where an exception is made for "whose controlling expression is not a constant expression". But as I argue above, it doesn't really help.

Ah. I hadn't noticed that addition. Very well. The one you're looking at is the most current C11 standard draft.

The compiler is already forced to keep track of whether a propagated constant is a constant expression for other reasons. For instance, sizeof(*(char (*)[1])a++) does not increment a, but sizeof(*(char (*)[non_constexpr_1])a++) does.

infinite loop - Is while(1); undefined behavior in C? - Stack Overflow

c infinite-loop undefined-behavior