How come these symbols: +!!"" = 1? c++ - c++

Recently my friend showed me an article that showed +!!"" is == to 1 in C++...
What subject does this fall under ? Where can I look into it ? Why is this true ? I can't find information about this anywhere

What subject does this fall under ?
Implicit conversions. And operators. And string literals. All of which are subtopics of expressions.
Where can I look into it ?
The c++ standard is the authoritative specification. There are also unofficial websites that describe the rules.
Why is this true ?
"" is a(n empty) string literal. String literals are arrays (of characters). Arrays decay to pointer to first element. The logical NOT operator (!) evaluates to false when the operand is a non null pointer. The NOT operator evaluates to true when the operand is false. The unary plus arithmetic operator implicitly converts the operand to integer. True is converted to 1.

”” is an array of const char. In most contexts, an array decays into a pointer to its first element. That’s what happens here. When you apply ! to a pointer, the result is true if the pointer is a null pointer, otherwise it’s false. The pointer is not a null pointer, so !”” has the value false. !false is true, so !!”” is true. Unary + promotes smaller types to int; in this case, it promotes the value true from bool to int. When true is promoted to int it becomes 1.

Related

What does an exclamation mark in array index do?

While perusing through my organization's source repository I came across this little gem:
RawParameterStorage[!ParameterWorkingIdx][ParameterDataOffset] = ...
Is this valid code? (It compiles) What does the exclamation mark here do?
An invert ~ operator might make sense, since it's commonly confused with the not ! operator in boolean expressions. However, it doesn't seem to make logical sense to impose the not ! operator on an array index. Any Thoughts?
!ParameterWorkingIdx Means ParameterWorkingIdx is 0, If it is, !ParameterWorkingIdx evaluates as true which might be implicitly converted to the indexer type (For example, 1 for integer indexer as in an array), otherwise, it evaluates as false.
If ParameterWorkingIdx == 0 then [!ParameterWorkingIdx] == [1].
If ParameterWorkingIdx != 0 then [!ParameterWorkingIdx] == [0].
It also depends on other stuff like:
The type of ParameterWorkingIdx.
overloading of ! operator by the type of ParameterWorkingIdx.
indexer overloading by the type of RawParameterStorage.
etc...
Taking a bit of a guess here, but that looks like a double-buffer pattern. ParameterWorkingIdx would flip-flop between 0 and 1 (probably with ParameterWorkingIdx = !ParameterWorkingIdx;).
Then, at any time, RawParameterStorage[ParameterWorkingIdx] would be the current buffer, and RawParameterStorage[!ParameterWorkingIdx] would be the previous buffer.
it doesn't seem to make logical sense to impose the not ! operator on an array index
It might: all it does here is convert zero to one, and any other number to zero.
We can infer from this code that RawParameterStorage probably has two elements at the top level.
P. S. Here, I assume that RawParameterStorage is an array (as you say it is). Furthermore, I assume that ParameterWorkingIdx is an integer (as its name implies). If, for example, either is a class with overloaded operators than the semantics could be completely different.
Is this valid code?
Yes it is. Suppose ParameterWorkingIdx to be an int, for !ParameterWorkingIdx, when used with operators !, it'll be contextually convertible to bool,
The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.
Then integral promoted to be used as the array index.
the type bool can be converted to int with the value false becoming ​0​ and true becoming 1.
So !ParameterWorkingIdx is equivalent with ParameterWorkingIdx == 0 ? 1 : 0, which is much more clear IMO.

Does the 'if' statement in C/C++ cast the operand to an integer?

When you use the if statement in C/C++, or any other logical operator, is the operand you pass to the statement cast to an integer for evaluation?
My current understanding was that the operand passed to the statement is cast to an integer to test whether or not it is non-zero (true), and that if you pass a pointer, this can be cast to an integer to evaluate with a 0/null value being defined as false.
I was under the impression that C++'s standard Bool values were simply typedef of an unsigned char with a value of 0 and 1.
Can anyone explain what's actually happening behind the scenes with this behavior?
In C++ bool is a standalone type that has nothing to do with unsigned char. And in C++ language the expression under if is indeed implicitly cast to bool type. Note: to bool specifically, not to int. For scalar types other than bool, the implicit conversion to bool is essentially defined through non-equality comparison to literal 0. I.e. values that compare non-equal are converted to true, while values that compare equal - to false.
In other words, in C++ statement
if (a)
is interpreted as
bool tmp = (bool) a;
// `tmp` is either `true` or `false`
if (tmp)
which for scalar types is interpreted as
bool tmp = a != 0;
if (tmp)
Note that this works "as expected" for pointer types as well. But instead of converting the pointer to int type, it actually works the other way around: it converts literal 0 to the proper pointer type.
For other types it could be something different, like a call to a user-defined conversion operator operator bool().
In C language the expression under if has to have scalar type. And it is implicitly compared to constant 0. Note that this does not involve converting the controlling expression it to int. Comparison to constant 0 is defined separately for all scalar types. E.g. for int it has its natural meaning, while for pointer types it is interpreted as comparison to null pointer. Now, the result of such comparison in C has type int and evaluates to either 0 or 1. That 0 or 1 is what controls what if branch is taken.
In other words, in C statement
if (a)
is immediately interpreted as
int tmp = a != 0;
// `tmp` is either `0` or `1`
if (tmp)
Additionally, your assumption that null pointer produces a zero int value when converted to int type is incorrect. Neither language makes such guarantee. Null pointer is not guaranteed to be represented by zero address value and is not guaranteed to produce zero value when converted to int.
In C++, the condition in an if statement is converted to a bool.
From the C++11 Standard:
6.4 Selection statements
4 The value of a condition that is an initialized declaration in a statement other than a switch statement is the value of the declared variable contextually converted to bool (Clause 4). If that conversion is ill-formed, the program is ill-formed.
A different section, 4.12 Boolean conversion, of the standard talks about conversions to bool.
4.12/1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

compiler allows 'char * k= false'? Why?

I found strange from my point of view compiler behavior, It allows assign Boolean value to * char.
char * k= false;
Why? But after assignment * char is still not initialized. Why compilers doesn't allows assign int value?
It will be implicitly converting the boolean value false to an integer with value zero and as such declaring a NULL pointer. It is effectively no different from
char* k = 0;
which is valid syntax
C++03 Standard, #4.10:
A null pointer constant is an integral constant expression (5.19)
rvalue of integer type that evaluates to zero.
5.19:
An integral constant-expression can involve only literals (2.13),
enumerators, const variables or static data members of integral or
enumeration types initialized with constant expressions (8.5),
non-type tem- plate parameters of integral or enumeration types, and
sizeof expressions.
false is a boolean literal, therefore it falls into the category of a constant expression, so it can qualify as a null pointer constant.
false and true are shortcuts for 0 and 1. For pointer you use NULL which define NULL 0. So it correct syntax.
The compiler allows it because in C++ false is the same as 0 and NULL.
Personally, at least for assignments, I find it easier to understand and more correct to use NULL to indicate a null pointer.
Btw, before C++, on some systems NULL was actually a macro defined as (void*)0xffff; some background on that can be found in this answer.

Why this weird compatibility of bool and pointers in C++?

Not only is this valid and doesn't give any warnings even with -Wall:
void* p = false; // actually 'true' doesn't work here
bool b = "Hello, Boolean!";
but also this compatibility rule permits selecting an overloaded function/operator for a wrong type. Let's say you overloaded your operator << for all fundamental types and you forgot to overload the void pointer, then the compiler may select the version that takes bool, or the other way around.
So what is it that makes this compatibility rule more important than the weird (and highly undesirable) side effects with overloaded functions?
(Edit: removed all references to C, they were wrong: the conversion rules are basically the same in C.)
What do you mean by "C can handle this correctly"? C doesn't permit function overloading, so you are guaranteed to have the bool <-> pointer conversion you're complaining about.
Are you asking why this conversion exists?
The first is not actually a conversion bool -> pointer, but is recognizing that the literal false means 0, which is a valid pointer value. That's why it doesn't work with true, and it doesn't work with a bool variable.
The second is because it's nice to be able to write:
if (p)
instead of
if (p != 0)
to check if a pointer holds a null pointer value.
EDIT: Rules from the standard influencing T* p = false;:
A null pointer constant is an integral constant expression prvalue of integer type that evaluates to zero
and
Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.
and
The Boolean literals are the keywords false and true. Such literals are prvalues and have type bool.

behavior of bool with non-boolean operators

What I really want is a ||= operator.
old_value = old_value || possible_new_value;
old_value ||= possible_new_value;
The second line is a compiler error (c++ doesn't have a ||= operator).
So what are my other options?
old_value += possible_new_value;
old_value |= possible_new_value;
While I'm on the subject how does bool behave with other non-boolean operators?
-
-=
&
&=
...
I can verify these empirically, but I'm most interested in what the standard says.
According to 4.7 (Integral conversions), paragraph 4, "If the destination type is bool, see 4.12. If the source type is bool, the value false is converted to zero and the value true is converted to one." In 4.12, "An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true."
In a context where bool operands are not allowed but integral operands are, the bool will be converted to an integral type. When the integer result is stored in a bool variable, it will be converted to bool.
Therefore, you will be able to use + and * as boolean or and and, and you can use | and & also. You can't get away with mixing them, as (bool1 + bool2) & bool3 will yield false if all three variables are true. ((1 + 1) & 1 is 2 & 1, which is 0, or false.)
Remember that | and || don't work identically even here. | will evaluate both sides, and then evaluate the bitwise or. || will evaluate the first operand, then only if that was false will evaluate the second.
I'm not going to discuss the stylistic issues here, but if I did anything like that I'd be sure to comment it so people knew what I was doing and why.
The standard sayeth:
4.5-4 "Integral Promotions"
An rvalue of type bool can be
converted to an rvalue of type int,
with false becoming zero and true
becoming one.
5.17-7 "Assignment Operators"
The behavior of an expression of the
form E1 op= E2 is equivalent to E1 =
E1 op E2 except that E1 is evaluated
only once. In += and -=, E1 shall
either have arithmetic type or be a
pointer to a possibly cvqualified
completely defined object type. In all
other cases, E1 shall have arithmetic
type.
4.12-1 "Boolean Conversions"
An rvalue of arithmetic, enumeration,
pointer, or pointer to member type can
be converted to an rvalue of type
bool. A zero value, null pointer
value, or null member pointer value is
converted to false; any other value is
converted to true.
So this means that
b1 += b2
Where b1 and b2 are boolean will be equivalent to
b1 = b1 + b2
And b1 and b2 will be promoted to 0/1 integers, and then converted back to boolean on the rule that anything other than 0 is true.
So the truth table is
true false
true true true
false true false
so += does in fact work as ||= according to the standard. However, this will probably be confusing other programmers, so I would avoid it still.
Could you just use the ternary operator?
old_value = !old_value ? possible_new_value : old_value;
Don't use |= and &= with bools. They may work most of the time, but it is still wrong. Usually the bool type is just a glorified int or char. In older code that I've worked with, BOOL is just typedef'd to int or char. In these cases, you can get the wrong answer if somehow the bits have been manipulated (For example, 1&2 is 0 (false)). And I'm not sure, but I think the result of bitwise operators is going to be an int, even for bools.
if (!old_value)
old_value = possible_new_value;
This is a direct equivalent of the original condition. It might generate simpler code since it won't always assign to old_value - but I wouldn't expect the performance difference to be easily measurable in a big program.
One difference is that the logical operators such as || guarantee the order of evaluation and provide short-circuiting, where the bit-wise and arithmetic operators do not.
I believe the compiler will treat the non-logical operators by converting the bools to numeric values (0, 1) applying the operator and converting back. These conversions are strictly defined by the standard, e.g.:
An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false any other value is converted to true.
Nasty macro hackery:
#define UPDATE(x) x = x
UPDATE(old_value) || possible_new_value;
But I don't recommend this at all. Macros like this are a very bad idea for several reasons.
A more sane function, but without the short-circuiting:
bool set_or(bool &old, bool value) {
return (old = old || value);
}
...
bool v = false;
set_or(v, true);
I believe the standard explicitly defines true and false as 1 and 0, so you can safely use bitwise operators on bool values. Other types that might be implicitly treated as bools in another context should be explicitly converted for this to work reliably.
I've seen Microsoft's compiler generate an ugly warning each time you do this, because it thinks there's a danger in implicitly converting the int result back to bool.