I have a simple question for C.
What does this statement mean?
if (!someArray[i])
I know that the operator ! means NOT. But i cannot get my head around it.
Thank you!!
if (!someArray[i]) means if someArray[i] is zero (or convertible to false) then the code inside the if block will be executed, otherwise it will not be executed!
If someArray[i] is not convertible to boolean value OR if the type of someArray[i] doesn't define the operator ! returning boolean value (or a value convertible to it), then your code will not compile.
Note: all numbers (int, float, double, char, etc) and pointers of any type, are convertible to boolean value.
In C, it's equivalent to writing
if (someArray[i] == 0)
From the C language standard (n1256):
6.5.3.3 Unary arithmetic operators
Constraints
1 The operand of the unary + or - operator shall have arithmetic type; of the ~ operator, integer type; of the ! operator, scalar type.
Semantics
...
5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).
As Kos and John Dibling pointed out, the situation in C++ is different. From the latest C++ draft (n1905)
5.3.1 Unary operators
...
8 The operand of the logical negation operator ! is implicitly converted to bool (clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool.
It means simply that if the value in someArray[i] is interpreted as false (either a zero value, or boolean false), then the code will enter the if block.
Assume the following uncompiled/untested code:
//we make an array with some chars, but have one as NULL (0)
char someArray[] = { 'a', 'b', 'c', 0, 'e' };
//we loop through the array using i as the index
for(int i = 0; i < 5; ++i)
{
if(!someArray[i]) //if this entry is null (0) or false, show an error:
{
printf("%d does not have a char!\n", i);
}
else //otherwise, print the contents
{
printf("%d is %c\n", i, someArray[i]);
}
}
Expected output would be:
0 is a
1 is b
2 is c
3 does not have a char!
4 is e
The ! (not) operator will return true if the expression evaluates to a 0. So:
class SomeObject
{
}; // eo class SomeObject
std::vector<int> intVector;
std::vector<long> longVector;
std::vector<SomeObject*> objectVector;
intVector.push_back(1);
intVector.push_back(0);
longVector.push_back(4049);
longVector.push_back(0);
objectVector.push_back(new SomeObject);
objectVector.push_back(NULL); // or nullptr if you're on C++0x, or even just 0!
if(!intVector[0])
{
// false, intVector[0] is not zero.
}
if(!intVector[1])
{
// true! intVector[1] is zero
};
And the same holds true for the other two vectors. Incidentally, the ! operator can be overidden by a class to change the behaviour.
Note also, that this is different from C# which requires that the expression be of a boolean type:
int i = 0;
if(!i) { /* compile error in C# */ }
if(i == 0) { /* ok in C# */ }
bool b = false;
if(!b) { /* ok in C# */ }
if(!(i == 0)) { /* also ok */ }
Perhaps the important thing to know about in the statement if (!someArray[i]) is the precedence of the operators.
first [ is evaluated, then ! is evaluated.
Writing it in a longer form might be
sometype a = someArray[i];
if(!a)
Related
I was hoping someone could explain how the condition statement of return (i % 2) ? &odd : &even; is able to determine if i is even or odd.
I am confused because &odd and &even are references to int odd[] and int even[]. It is my understanding the a condition statement does not "iterate" through the array and check all values in the array in order to check the condition of (i % 2) for a match. below is the code. I hope I was clear enough.
#include <iostream>
int odd[] = { 1, 3, 5, 7, 9 };
int even[] = { 0, 2, 4, 6, 8 };
decltype(odd)* arrptr(int i) { // equivalent to int (*arrPtr(int))[5] or
// auto arrPtr(int i) -> int(*)[5]
return (i % 2) ? &odd : &even;
}
int main()
{
arrptr(3);
system("pause");
return 0;
}
This is to explain the confusion you've as I see in the comments you posted to the other answer.
How does the conditional statement know the difference between what is a even number or an odd number?
It doesn't. It simply evaluates the first expression and checks the truth value. Like an if, you insert the logic on deciding if i is even or odd. Usually this is done with the interger reminder operator i % 2.
The expressions in the conditional statement are nothing more than references to an array named &odd[] and &even[]. There is nothing in the program that tells the program what even or odd number means.
No, the second and the third arguments are what &odd[] and &even[] are. You missed the first; it is a conditional expression which will be evaluated for a truth value.
i % 2 will return 0 if i is even, else 1 if i is odd. This integer value will be implicitly converted into a boolean value since the expression is evaluated in a boolean context. In C and C++ any non-zero value is true else false. Hence if i is even it'll return false, else true.
I think what is confusing you is the name of operands 2 and 3; mentally rename them into evenArray and oddArray. What the operator does is, it returns an array. Which array? That it decides based on the first operand, which in turn decides it with parity (even/odd) of the argument i.
That is the C conditional operator ?:. The part before the question mark is a Boolean expression. If it evaluates to true then the part between the questions mark and the colon is executed otherwise the other part is executed. It's equivalent to:
if(boolean expr) { expression1 }
else { expression2 }
In your example, you could write:
decltype(odd)* arrptr(int i)
{ if(i % 2) return &odd;
else return &even;
}
You might be confused by how the arrays are named. The function returns a pointer to an array depending on the value of i (the function knows nothing about the numbers stored in the arrays). That is, if i is an odd number we return a pointer to the array named odd and if it i is even we return a pointer to the array named even. The i % 2 part tells you if i is even or odd. Hope this helps.
What's the differences of if(x==0) vs. if(!x)? Or are they always equivalent? And for different C++ build-in types of x:
bool
int
char
pointer
iostream
...
Assuming there is a conversion from a type to something that supports if (x) or if (!x), then as long as there isn't a DIFFERENT conversion for operator int() than opterator bool(), the result will be the same.
if (x == 0) will use the "best" conversion, which includes a bool or void * converter. As long as there is any converter that can convert the type to some "standard type".
if(!x) will do exactly the same, it will use any converter that converts to a standard type.
Both of these of course assume the converter function isn't a C++11 "don't default convert".
Of course, if you have a class like this:
class
{
int x;
public:
bool operator bool() { return x != 0; }
int operator int() { return x == 0; }
};
then if (x == 0) will do if ( (x == 0) == 0) and if (!x) will will do if (! (x != 0), which isn't the same. But now we're really TRYING to make trouble, and this is VERY BADLY designed code.
Of course, the above example can be made to go wrong with any operator int() that doesn't result in false for x == 0 and true for all other values.
if(!x)
is "if x is not false", that means that in order to evaluate that, you might have to cast x to a bool.
>> This can be harmful and if you wish to avoid it you should use something like the Safe Bool Idiom
if(x!=0)
means "if x is not 0", so that is evaluated comparing x to 0. That might also involve an implicit conversion.
>> Be careful when using pointers this way, C++11 introduces a nullptr to avoid the confusion of NULL==0 (semantically different): What exactly is nullptr?
Take into account what are you going to process
If it is a boolean, the results are pretty clear:
if (!false) // If false TRUE
if (false==0) // If false TRUE
If it is an integer, pay attention to the ! condition
if (0==0) // Unexpected behaviors are missing..
if (!-1) // False
if (! 0) // True
if (! 1) // False
For chars both conditions give me the same results:
if (! ' ') // nothing
if (' '==0) // nothing
if (! 'z') // nothing
if ('z'==0) // nothing
No this all depends on the type of x. For example,
if(cin)
is used in the stl to check if an iostream type hasn't had an error. There is no equivalent cin != 0.
Besides most operators are overloadable and conversions too.
Simply !x will return true for every "false" value (i.e, 0, null, false, etc.) whereas x!=0 will return true, iff x is not equal to 0.
I saw some C++ code like this:
bool MyProject::boo(...)
{
bool fBar = FALSE;
....
return !!fBar;
}
I couldn't think of any difference between returning fBar directly in this case and returning !!fBar. How two negatives make a difference?
Thank you
In your example, there's no difference between returning fBar and returning !!fBar.
In other cases, e.g. when a user-defined type such as BOOL (typedef-ed to be int) is used, the !! construct has the effect of coercing any non-zero value to true; i.e. !!fBar is equivalent to fBar ? true : false. This can make a difference if fBar can be 5 and you want to compare it against TRUE, which is defined to be (BOOL)1.
This is typically done to avoid compiler warnings in situations when a non-bool value has to be converted to bool type. Some compilers (like MSVC++) issue a "performance" warning when a non-bool value is implicitly converted to bool. One way to suppress this warning is to use an explicit conversion. Another way is to use the !! combination.
However, in your case the argument of return is already declared as a bool, meaning that the above reasoning does not apply. (Are you sure it was bool and not, say, BOOL?). In that case there's no meaningful explanation for that !!.
!! "is" "to boolean" operator (not really, it is two negate operators). It make no different is this case. However, it will make difference if is not bool.
e.g.
int fBar = 2; // !!fBat evaluate to 1
bool b = (fBar == true) // this is false
b = fBar; // this is true
b = !!fBar; // this is also true
typedef int MyBool; // say some library use int as boolean type
#define MY_TRUE 1
#define MY_FALSE 0
MyBool b2 = fBar; // this evaluate to true, but not equal to true
if (b2 == MY_TRUE )
{
// this code will not run, unexpected
}
if (b2)
{
// this code will run
}
MyBool b3 = !!fBar;
if (b2 == MY_TRUE )
{
// this code will run
}
if (b2)
{
// this code will run
}
Here is my code:
int main()
{
int input;
bool isZero = false;
while (!isZero)
{
...
if (0 == input)
{
isZero = true;
}
else
{
isZero = false;
}
}
return 0;
}
the program does what its supposed to, but I feel like the !isZero expression is not foolproof.
is
bool isZero = false;
while(!isZero);
{
....
}
the same thing as
bool isZero = false;
while(isZero == false)
{
...
}
why or why not?
Also, in which cases does true represent 1, and in which cases does it represent any nonzero number?
While requires the condition to be a Boolean and !isZero is already a Boolean. Equality operator generates a Boolean, so again isZero == false is a Boolean. So the only thing you changed is adding another operator and (possibly) slowing down loop a little (AFAIR comparison is slower than bit operators).
Operations on Boolean values are similar to operations on integer values. Your concerns can be then translated into integers: "Hey, x == 1 is not foolproof, I have to check, whether x - 1 == 0".
The bottomline is, that !isZero is absolutely foolproof enough.
As for int to bool conversions, the standard says,
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. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
C++ is very lenient in its requirements for a conditional. It accepts booleans, and it will implicitly cast any integer to a boolean (where 0 is false and non-zero is true), and it will also implicitly cast any pointer to a boolean (since pointers are unsigned integers. In that case, NULL would be false, and any other pointer would be true). Thus, the following all evaluate to true, so the while will execute.
int i = 4;
char c = '0';
bool b = true;
void * p = 0xdeadbeef;
while (i) // ...
while (c) // ...
while (b) // ...
while (p) // ...
While the following won't evaluate to true, so the while won't execute.
int i = 0;
char c = '\0';
bool b = false;
void * p = NULL;
while (i) // ...
while (c) // ...
while (b) // ...
while (p) // ...
According to C++, all of these are allowed.
When you're looking at a boolean in your expression, it's redundant to put a == operator on it. Whether b above is true or false, it makes perfect sense to say while (b), and you don't need while (b == true). As for all of the others, each programmer makes their own choice. My personal preference is to explicitly compare all non-booleans. The statement int i = 5; while (i) may be legal in C++, but it just doesn't read clearly. I would much rather see int i = 5; while (i != 0). It's unnecessary, but doesn't cost you any extra processor operations, and is explicit as to its intent.
This may be a silly thing to ask but I am confused with compilation error while trying to use the safe bool idiom while reading this article. Below is my code and I have indicated the lines where i get errors in main() function.
// is OK case
class BoolVer_OK {
bool m_OK;
public:
BoolVer_OK(bool ok) : m_OK(ok){}
operator bool() { return m_OK; }
};
// Not OK Case
class BoolVer_NotOK {
bool m_notOK;
public:
BoolVer_NotOK(bool ok) : m_notOK(!ok){}
bool operator !() const{ reportexecution; return !m_notOK; }
};
main()
{
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
return 0;
}
Why we didn't get error at #Line1 while we get at #Line2. Both results in a boolean value before << operator.
ok supports operator bool, and C++ has this nice functionality called implicit casting and also promotion, and in this case for the binary shift operator <<, the bool is promoted to an int, and this is then shifted by 1.
In the second case, you've not provided that operator, and hence there is nothing to implicitly convert (and promote) to int, and you get the error. Try calling !notOk before the shift, now there is a bool, which will be promoted.
I don't think the compiler would automatically insert a call to operator! and then negate that to get you the bool you want. From what I see in the link you provided, they do their tests with a double negation, !!.
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
This happens because ok is converted to bool implicitly (overloaded operator), whereas notOK doesn't have that operator.
Test out the following code:
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
int z = ok<<1; // is valid
//notOK << 1; // error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
int x = false << 1;
return 0;
The booleans on the left-side of the shift operator are converted to ints and then shifted.