What does double not (!!) used on a non-boolean variable do? [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Double Negation in C++ code.
I am working with production code where I have run across statements like this a few times:
Class.func(!!notABool);
The first couple of times I dismissed it as a programmer quirk (maybe to emphasize that it is a conditional statement rather than a number being passed into func?) but I have run across several statements that use the above and now I am wondering whether it actually makes a difference or not. In most cases notABool is a number(int, float, double... I have seen all 3) My initial guess was that it is akin to typing:
Class.func((bool)notABool);
but I am not entirely sure?

Yes, functionally it is exactly the same as doing (bool) notABool.
By definition, in C++ language the operand of ! is implicitly converted to bool type, so !!notABool is really the same as !! (bool) notABool, i.e. the same as just (bool) notABool.
In C language the !! was a popular trick to "normalize" a non-1/0 value to 1/0 form. In C++ you can just do (bool) notABool. Or you can still use !!notABool if you so desire.

For primitive types, yes, it's essentially equivalent to:
!(notABool != 0)
which in turn is equivalent to:
(bool)notABool
For non-primitive types, it will be a compiler error, unless you've overloaded operator!, in which case, it might do anything.

It's a legacy idiom from C, where it meant "normalize to 0 or 1". I don't think there's a reason to use it in C++ other than habit.

It's converting BOOL (define for int) to c++ bool. BOOL is a define that in some cases for true can contain different integer values. So for example BOOL a = (BOOL)1; and BOOL b =(BOOL)2; both pass check for true. But if you'll try to compare you'll find that a not equals b. But after conversion !!a equals !!b.
(bool)notABoo - is not akin, because you'll convert type of variable byte still'll have different values. !! converts not only type but in some cases values too.

Related

no comparison in if() judgement but seems give a boolean value

if(!word.size()){
return true;
}
whole code screenshot
how here use string.size() lonely to return a boolean value?
I googled the string.size() method although i already know it returns a int value,but here it works like a true/false method;
Lots of things in C++ can be coerced to Booleans. Off the top of my head.
Booleans are trivially convertible to Booleans
Numbers (int or double) can be converted to Boolean; zero is false and anything else is true
Streams (like fstream instances or cout, for instance) can be converted to Boolean and are true if the stream is in "good" condition or false if there's a problem
As indicated in the comments, you shouldn't use this in real code. if (!word.size()) is silly and confusing an should only be seen in code golf challenges. Coding isn't just about making the computer understand what you mean; it's about making sure future readers (including yourself six months down the line) understand as well. And if (word.empty()) conveys the exact same intent to the computer but is much more understandable to the human reader at a glance.
So why does C++ allow this if it's discouraged? Historical reasons, mostly. In the days of C, there was no dedicated bool type. Comparisons returned an integer, and the convention was that 0 meant "false" and anything else (usually 1) meant true. It was the programmer's job to remember which things were Booleans and which were actual integers. C++ came along and (rightly) separated the two, making a special type called bool. But for compatibility with C, they left in the old trick of using integers as Booleans. Successor languages like Java would go on to remove that capability. if (myInteger) is illegal in Java and will give a compiler error.
The language checks if the condition inside the conditional is true or false. In this case, the int value gets converted into a boolean. If the size returns 0 this will get converted to false, any other value will be converted to true.

Why write `!!x`, when `x` will do? [duplicate]

This question already has answers here:
Double Negation in C++
(14 answers)
What is the usage of "!!" (negating twice)? [duplicate]
(3 answers)
Confused by use of double logical not (!!) operator [duplicate]
(5 answers)
Closed 2 years ago.
I often see experienced programmers write !!x, even though the expected expression is a Boolean (i.e., zero or not zero) and not an integer.
For example, a line from boost:
BOOST_ASSERT(!!p); // where `p` is a pointer
What's the point of !!p when just p will do?
What I understand by a Boolean parameter is an expression converted to a value of integral type, and the value is compared against zero, explicitly or implicitly (with if or its ternary operator equivalent).
Thus, anything that takes a Boolean and expects only 0 or 1 is wrongly implemented, if my understanding of Boolean is correct.
For clarification: it's obvious that ! converts to bool; the question is explicitly asking for why.
By default, BOOST_ASSERT(expr) expands to assert(expr). That C++ assert function takes a scalar argument, not bool. Thus, your statement, "the expected expression is a boolean," is not correct.
Classes in C++ can implement operator bool(); the basic_stream classes are examples of such: assert(std::cin) will not work. The !! operator forces the use of std::cin::operator bool(), and bool after !! will be evaluated to int 0 or 1. This is shorter than assert(bool(std::cin)).
If I were a boost author, I would expand BOOST_ASSERT(expr) to assert(!!(expr)) - as is done for ( BOOST_LIKELY(!!(expr)) ? ((void)0) ).
Closely related to the question
Warnings.
Some compilers issue warnings.
Overflow of the integer storing the Boolean.
I'll just quote the comment mentioning the behaviour
The compiler would treat the values the same either way if it's only used as an operand to an if or &&, but using !! may help on some compilers if if (!!(number & mask)) gets replaced with bit triggered = !!(number & mask); if (triggered); on some embedded compilers with bit types, assigning e.g. 256 to a bit type will yield zero. Without the !!, the apparently-safe transformation (copying the if condition to a variable and then branching) won't be safe.
Related
Some consider defining operator bool() to be "unsafe". And to have an idiomatical way to convert to bool, they define bool operator !().
So writing !!obj is to support such users. And it doesn't even hurt to do so!

Strange definition of FALSE and TRUE, why? [duplicate]

This question already has answers here:
Why #define TRUE (1==1) in a C boolean macro instead of simply as 1?
(8 answers)
Closed 9 years ago.
In some code I am working on I have come across strange re-definitions of truth and falsehood. I have seen such things before to make checks more strict/certain, but this one is a little bizarre in my mind and I wonder if anyone can tell me what could be a good reason for such definitions, see below with my comments next to them:
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE) // why not just define it as "true" or "1"?
There are many other strange oddities in this code base. Like there are re-definitions for all the standard types like:
#define myUInt32 unsigned integer // why not just use uint32_t from stdint?
All these little "quirks" make me feel like I am missing something obvious, but I really can't see the point :(
Note: Strictly this is c++ code, but it could have been ported from a 'c' project.
The intent appears to be portability.
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE) // why not just define it as "true" or "1"?
These have boolean type in languages that support it (C++), while providing still-useful numeric values for those that don't (C — even C99 and C11, apparently, despite their acquisition of explicit boolean datatypes).
Having booleans where possible is good for function overloading.
#define myUInt32 unsigned integer // why not just use uint32_t from stdint?
That's fine if stdint is available. You may take such things for granted, but it's a big wide world out there! This code recognises that.
Disclaimer: Personally, I would stick to the standards and simply state that compilers released later than 1990 are a pre-requisite. But we don't know what the underlying requirements are for the project in question.
TRWTF is that the author of the code in question did not explain this in comments alongside.
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
I think it is because the type of the expression (1!=1) depends on the language's support for boolean value — if it is C++, the type is bool, else it is int.
On the other hand 0 is always int, in both languages, and false is not recognized in C.
Strictly this is c++ code, but it could have been ported from a 'c' project.
This is about portability as mentioned previously, but it actually goes far beyond. It's a clever exploit of the language definitions in order to comply with the languages.
These absurd looking macros are not as absurd as they appear at first glance, but they are in fact ingenious, as they guarantee for both C and C++ that TRUE and FALSE have the correct values (and type) of true and false (even if the compiler is a C compiler which doesn't have those keywords, so you can't trivially write something like #define TRUE true).
In C++ code, such a construct would be useless, since the language defines true and false as keywords.
However, in order to have C and C++ seamlessly interoperate in the same code base, you need "something" that works for both (unless you want to use a different code style).
The way these macros are defined is a testimony of the C++ standard on being explicitly vague about what values true and false actually have. The C++ standard states:
Values of type bool are either true or false.
[...]
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 bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
Note how it says that two particular values exist and what their names are, and what corresponding integer values they convert to and from, but it does not say what these values are. You might be inclined to think that the values are obviously 0 and 1 (and incidentially you might have guessed right), but that's not the case. The actual values are deliberately not defined.
This is analogous to how pointers (and in particular the nullpointer) are defined. Remember that an integer literal of zero converts to the null pointer and that a nullpointer converts to false, compares equal... blah blah... etc etc.
A lot is being said about which converts to what and whatnot, but it doesn't say anywhere that a null pointer has to have a binary representation of zero (and in fact, there exist some exotic architectures where this isn't the case!).
Many of them have historical reasons such as old codes migrated from C, codes from non-standard C++ compilers, cross compiler codes (portability), to support backward compatibility, following code styles, bad habits.
There were some compilers which had not <cstdint> for integer types like uint32_t, or they had not <cstdbool>. A good programmer had to define everything and use pre-processors heavily to make his program well defined over different compilers.
Today, we can use <cstdint>, true/false, <cstdbool>, ... and everyone is happy!
The nice thing about this defintion is to avoid an implicit conversion from TRUE or FALSE to an integer. This is useful to make sure the compiler can't choose the wrong function overload.
C didn't have a native boolean type, so you couldn't strictly use "false" or "true" without defining them elsewhere - and how would you then define that?
The same argument applies to myUInt32 - C originally didnt have uint32_t and the other types in stdint, so this provides a means of ensuring you are getting the correct size integer. If you ported to a different architecture, you just need to change the definition of myUInt32 to be whatever equates to an unsigned integer 32 bits wide - be that a long, or a short.
There is a nice explanation which states the difference between false and FALSE. I think it might help in understanding bit further though most of the answers have explained it.
here

VB6 and C++ boolean literals

I am learning C++. I come from a background of: .NET and VB6.
I am intrigued about what the following webpage says about booleans: http://msdn.microsoft.com/en-us/library/ff381404(v=vs.85).aspx i.e.
"Despite this definition of TRUE, however, most functions that return a BOOL type can return any non-zero value to indicate Boolean truth. Therefore, you should always write this:
// Right way.
BOOL result = SomeFunctionThatReturnsBoolean();
if (result)
{
...
}
"
Does this apply to VB6 as well i.e. is there a problem saying: If BooleanValue = True Then?
The Windows API was designed to be used from C programs. Which until C99 didn't have a bool type. And still doesn't completely, C99 was never implemented by the Microsoft compiler for example. So they had to come up with a workaround, one that's highly compatible with the way C compilers deal with logical values. An int where 0 is false and anything else is true. Thus the advice.
VB6 has a dedicated Boolean type and keywords for the literal values True and False so doesn't quite have the same problem. You can however still get into trouble with poorly written COM servers. The underlying integral value for True is -1, highly incompatible with many other languages' implementation of a logical boolean type. Including C. There's a good reason for VB6 being the oddball, its And and Or operators don't distinguish between a logical and a arithmetic and/or. By making True equal to -1 and False equal to 0 there is no difference. Trouble can arise when a COM server returns a 1 to indicate true instead of VARIANT_TRUE.
But most of all, writing If booleanVariable = True Then is just ugly and nails on the blackboard for many programmers. Just write If booleanVariable Then and be done with it.
Not in VB, no, as True/False are real boolean values. In C/C++ however, BOOL is just a #define of int, thus you can assign a BOOL variable any integer value (TRUE in C is a #define of 1 (usually) and FALSE a #define of 0).
If you want better overlap with your VB experience, use the bool datatype in C++ which uses actual true/false values.
EDIT: Of course, in VB you say If BooleanValue = TRUE. In C++, the equivalent is if (BooleanValue == true) (note the ==, which is a comparison operator, as opposed to = which is an assignment operator), but in C++ you can skip the == true comparison and just use if (BooleanValue).

String compare in c++

What is the difference between (x == "x") and ("x" == x) comparison in C++? Let's say x is a std::string. Is there any reason why one would be preferred over the other?
One is a string literal "X", and the other is an instance of std::string. Some advocate having the constant "x" on the left hand side, because that way you would get a compiler error if you use assignment = instead of equality ==:
if ("x" = x) // Error! Trying to assign to const char[]
if (x = "x") // Setting the value of x to be "x", and evaluating "x".
// Probably not what you want.
Other than that, there's really no difference.
I think both calls will result in call to bool std::string operator==(const std::string&, const std::string&).
This is because there are no implicit conversion operators from std::string to const char*, but there is implicit constructor from const char* to std::string.
EDIT:
on g++ 4.4.5 both comparisons works.
Here says the now closed question on Yoda Conditionals:
This is one of the things that I hate
most when I see it in someone else's
code. I know what it means and why
some people do it this way ("what if I
accidentally put '=' instead?"). For
me it's very much like when a child
goes down the stairs counting the
steps out loud.
Anyway, here are my arguments against
it:
It disrupts the natural flow of reading the program code. We, humans,
say "if value is zero" and not "if
zero is value".
Modern compilers warn you when you have an assignment in your condition,
or actually if your condition consists
of just that assignment, which, yes,
looks suspicious anyway
You shouldn't forget to put double '=' when you are comparing values if
you are a programmer. You may as well
forget to put "!" when testing
non-equality.
-mojuba
Accepted answer:
Ah, yes, "Yoda conditionals" ("If zero
the value is, execute this code you
must!"). I always point anyone who
claims they're "better" at tools like
lint(1). This particular problem has
been solved since the late 70s. Most
modern languages won't even compile
this, as they refuse to coerce the
result of the assignment to a boolean.
As others have said, it certainly
isn't a problem, but it does provoke a
bit of cognitive dissonance.
-TMN
I prefer using for NSStrings...
([x isEqualToString:#"x"])
or for c strings
strcmp(str1,str2);
There is no difference between those two conditions, other than maybe something internal. It's like holding two things in your hands, one in each hand, and comparing them - and then basing then factoring in which hand each one is in. ...That's not something that's a factor.