if we set float and double type to NaN then they are not equal to anything including themselves.
can such a thing happens for int?
Anything can happen if you compare an uninitialized variable to itself. It is after all undefined behavior. For initialized int variables, this can't happen.
Note that namespace-scope, class-static, and function-static int variables not explicitly initialized are given the value 0. Then they won't compare equal.
I have just tested with Clang:
int main() {
int x;
return (x == x);
}
When compiled with -O1, this returns 0 because the optimizer is allowed to assume that x has no stable value.
GCC is more forgiving with the above, returning 1. The following makes GCC return 0 too (obviously not doing the branch is cheaper if you are allowed to choose):
int main() {
int x;
if(x == x) {
return 1;
}
return 0;
}
In the end, the result is not only dependent on the CPU executing the code, but also from anything else in the toolchain.
Although it's certainly unusual, C++ does allow int
to be NaN
.
First, it's possible for int
to store information besides its numeric value. §3.9.1/1:
For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types.
Then, numeric_limits<int>::has_quiet_NaN
and has_signaling_NaN
are not required to be false
for any type. §18.2.1.2/34-36:
static const bool has_quiet_NaN;
34 True if the type has a representation for a quiet (non-signaling) ‘‘Not a Number.’’
35 Meaningful for all floating point types.
36 Shall be true for all specializations in which is_iec559 != false.
"Meaningful for all floating point types" is a little troublesome as it opens the possibility that the value could be meaningless, but that's certainly an extrapolation.
If numeric_limits<int>::has_quiet_NaN == true
, then numeric_limits<int>::quiet_NaN()
returns such a value.
Obviously, this is not something you should worry about in your code.
It cannot happen when you compare plain initialized int variables.
It can happen for int comparisons when you reference a hardware register, e.g. something like:
*timeRegister == *timeRegister
It could also happen when you compare a volatile int variable to itself which is modified by a signal-handler during the comparison.
This perfectly possible if you compare uninitialized variables.
In C++ language an uninitialized variable is not guaranteed to hold a stable value. In theory operating with uninitialized values produces undefined behavior. In practice reading the value of the same uninitialized variable multiple times can easily result in different values being read. The most obvious practical reason for this is that the variable was optimized to some CPU register.
In order to manage the limited amount of CPU registers efficiently, optimizing compilers operate with the notion of value lifetime of a variable. Value lifetime is essentially the period during which the variable holds a specific stable value. Value lifetime begins when the variable is initialized and ends when it is re-initialized to another value (or when its accessed for the very last time). Within the period of "value lifetime", the value must be stable, so the CPU register cannot be used for other purposes (or it have to be carefully saved and restored every time it is used for other purposes).
Outside the period of value lifetime, there's no need to preserve the value of the register, so it can be freely used for other purposes. For this reason, if some variable is represented by a CPU register, but not initialized (i.e. if its value lifetime hasn't begin yet) its observed value can change absolutely unpredictably, producing the new value every time the variable is read, because the contents of the corresponding CPU register changes for some unrelated reasons.
This might easily result in a == a
evaluating to false
with uninitialized a
. Of course, it is rather surprising to see it happen for two reads that appear to be located so "close" together. But it still can happen. This behavior is prefectly standard. The standard does not guarantee the stability of an initialized variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With