The condition in an if statement is evaluated as a boolean. If the expression evaluates to zero, that's equivalent to false. It is non-zero, it's true. A null pointer is zero, and so evaluates to false.
I apologize for fussing over this question. I understand the outcomes of evaluation above but taking it a step back how does array evaluate to anything given that it is an array.
the NOT operator just allows one to avoid having to write code like this, it gives us the 'else' condition directly:
1 2 3 4 5 6 7 8
if (array)
{
// do nothing
}
else
{
return;
}
In this case, there's no particular 'magic' involved. Though with user-defined types (classes) one could define the ! operator to do something specific, but that's another story.
We're left with the simple logic which goes,
evaluate the expression. If it is zero, interpret it as logical false. Anything non-zero is considered logical true.
ok, so array is evaluated to a (number) - if so what number is that? I think somewhere down the line I missed something about (expressions) and evaluations ().
What number is that - well it is the address of the location pointed to. If the function was called with an array as the first parameter, then the number is the address of that array.
I think it might confuse the discussion a bit that a pointer variable in the example is named "array" and it might point to an array.
The operator! is unary. It has one bool operand and it returns a bool value.
If the operand is not bool, then a conversion to bool must occur before the NOT is evaluated.
Pointer's value is an address. Address is a number. A number is either zero or non-zero. There is an implicit conversion from char/number/pointer to bool: 0 -> false, non-zero -> true.
Pointer's value is an address. Address is a number. A number is either zero or non-zero. There is an implicit conversion from char/number/pointer to bool: 0 -> false, non-zero -> true.
An address is an address. A pointer that compares equal to nullptr (and is therefore required to evaluate to false in the context of a boolean expression) may not contain the bit pattern for 0.
Pointer's value is an address. Address is a number. A number is either zero or non-zero. There is an implicit conversion from char/number/pointer to bool: 0 -> false, non-zero -> true.
That was part of the missing piece for me.
The implicit conversion makes possible a comparison. By itself !(array) I didn't see a comparison possibility available -- looked like it was being compared to itself. It all made sense to me when the implicit conversion to bool that makes a comparison possible was brought to discussion. Now there are at least 2 decision states possible from one entity !(array).
You were correct about the end result of the expression. You named the possible outcomes but it was the implicit conversion to bool that allowed the expression to be evaluated as such in the first place: zero, non-zero and null pointer.
I had assumed it would follow naturally that a non-null pointer is not zero, and so evaluates to true.
Again, we're oversimplifying. A null pointer is required to compare equal to a literal 0. It is not required to be 0. Assigning a pointer the literal 0 is required to set it to the value that indicates it is a null pointer, which may or may not be 0. See the link I posted up-thread.
> but it was the implicit conversion to bool that allowed the expression to be evaluated as such in the first place
Yes; that is the essence - the implicit conversion from pointer to bool.
Note that while any pointer can be implicitly converted to bool (either true or false), for some pointers, there is no direct conversion (either implicit or explicit) to any other integer type.
1 2 3 4 5 6 7 8 9 10 11 12 13
struct A
{
void foo() const {}
};
int main()
{
auto pointer = &A::foo ;
bool not_null = pointer ; // fine: implicit converstion from pointer to bool
int not_zero = reinterpret_cast<int>(pointer) ; // *** error: invalid cast
not_zero = static_cast<int>(pointer) ; // *** error: invalid cast
}