The value of comparison expression using any of ==, !=, <, >, <=, => will be a value 1 or 0 for true and false respectively, and, due to history, will be of type int.
_Bool type (for which bool is a macro alias defined in <stdbool.h>) can only store values 1 and 0. Additionally, when converting to _Bool, any nonzero value will be converted to 1. C11 6.3.1.2:
- When any scalar value is converted to
_Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1. [59]
[59] NaNs do not compare equal to 0 and thus convert to 1.
Therefore the following is valid:
bool QueueIsEmpty(Queue *pq)
{
return pq->items == 0;
}
The !x unary operator is exactly equivalent to x == 0 semantically and syntactically in all contexts, and therefore the former can be substituted everywhere in place of the latter, therefore the following is valid as well:
bool QueueIsEmpty(Queue *pq)
{
return !pq->items;
}
and the following is also valid for a function with opposite semantics:
bool QueueHasItems(Queue *pq)
{
return pq->items;
}
All of the functions have the same semantics regardless of the type of pq->items provided that the value of this expression has a scalar type (i.e. boolean, integer, pointer, real or complex floating point), or decays to one (i.e. if items is an array, then it will always be true...); and if it is not a scalar type then the code should fail to compile...
This compiles on x86-64 to
QueueHasItems:
cmp QWORD PTR [rdi], 0
setne al
ret
i.e. al is set as the result of zero/equality flag after cmp pq->items, 0.