Defining double exclamation? - c++

I understand what a double exclamation mark does (or I think I understand) but I am not sure how it is defined on a random object. For example in the code snippet below:
Assignment *a;
if (!getAssignment(query, a))
return false;
hasSolution = !!a;
if (!a)
return true;
How do I know what value will the double exclamation mark result in ? In other words does it always convert to true ? false ? or can you define a behavior for it such as executing a method to determine the result (how does the object know how to act in this situation) ? I am bit confused about this piece of code due to all these exclamation stuff going on.. Any explanation is appreciated.
Hope I was clear and thanks.

a is a pointer. In C++, nullptr is defined to be an invalid pointer. !pointer turns a nullptr pointer into true and a non nullptr pointer into false. !boolean turns true into false and false into true. It will always work.
!(!a) is a useful way to think of it.

Don't think of it as "double exclamation mark", think of it as two separate operators, one running on the result of the other.
For all primitive types, it will "work". !a is equivalent to a == 0, so !!a is equivalent to !(a == 0), which in turn is equivalent to a != 0.
For user-defined types, it won't compile unless they overload operator !. But obviously, in this case, the behaviour could be almost anything.

!! is not a single token in C++ and simply resolves to applying the ! operator twice.
As a is a pointer and not an object of class type the ! cannot be overloaded. It is defined to return true if a is a null pointer and false otherwise.
The second application of ! simply negates the result of the first !.
The expression !!a is equivalent to a != 0.

The code is horribly complicated. In reality, you want to test whether the getAssigment method is successful and whether the assigned pointer is non-null.
The code tests that, albeit in a convoluted fashion, taking advantage of weak typing, rather than trying to embrace explicitness and C++’ strong typing. As a consequence, it’s not idiomatic C++ and rather harder to understand than necessary.
In particular, don’t use !!a in C++. This is an established idiom in weakly-typed languages such as JavaScript to coerce a value into a boolean type. But in C++, this is not commonly used.
It’s not clear what the code does since hasSolution isn’t defined or used. However, I suspect that the code is supposed to be equivalent to the following:
Assignment *a;
return getAssignment(query, a) and a == nullptr;
(Before C++11, you need to write 0 instead of nullptr.)
However, this code still reveals a bad design: why is a passed by reference? Why isn’t it the return value? Worse, a is never used, so unnecessary. If a is indeed unnecessary, it should be left out completely. If it’s necessary, it should be the return value. In other words, the prototype of getAssignment should be as follows:
Assignment* getAssignment(the_type_of_query query);
And it should be used simply as follows:
Assignment* a = getAssignment(query);
Furthermore, I suspect that this code actually assigns memory ownership to the raw pointer a. This is strongly discouraged in modern C++. Either use no pointers or a smart pointer.

bool result = true;
result = !!result; // result = true, e.g. !result is false, !!result is !false.

There is no "!!" operator, so in fact, the statement is equivalent to:
hasSolution = !(!a);
So first, operator!() is called on expression "a", then another operator!() is called on the result. In the case of our code, "a" is a pointer to Assignement. C++ defines a special case for using operator!() on a pointer type: it returns a bool which is true if the pointer is null and false otherwise. In short, the same as the expression (a == 0). Calling operator!() on the result of (!a), which is a bool, simply reverts the result, i.e. returns true if (!a) is false and false if (!a) is true.
So in conclusion, (!!a) return the same result as (a != 0). This is because "a" is a pointer.

The easiest way to remember double-negation !!a is to narrow a!=0 to 1 and a==0 to 0.
Which is in boolean context (i.e. C++) true or false.

Related

Null parameter check C++

I have a function that solves one of 4 kinematic equations. The parameters are floats, and Is there a way to distinguish between a NULL parameter and a parameter with a value of 0. I've read up on the subject and it seems that NULL and 0 are the same. The reason I want to distinguish a 0 from a form of "nothingness" is because a 0 value assigns a value and "nothingness" shows that we don't know what that value is.
float doSomething(float& foo, float& bar, float& goo, float& baz){
if(foo == (insert_null_value_here)){
return (foo_after_we_did_some_equation);
}
}
The "null" value can't be NULL or 0 as I already discussed. If the parameters were all pointers to floats, would this work if I checked for "nullptrs"?(Not my main question) Even if the former question is yes, what value can I use for non-pointer/reference types?(Re-statement of main question)
There is no such thing as "a null parameter". Those references cannot compliantly "be null".
(It's important not to conflate this with the idea of a null pointer, which used to have value zero for legacy reasons — with a macro NULL defined to be zero for "convenience" — but nowadays is nullptr.)
If you want to make those values optional, use boost::optional, which forms a wrapper around a data member and a boolean indicating whether the member is populated:
float doSomething(boost::optional<float>& foo)
{
if (foo) {
return someEquation(foo.get());
}
return somethingElse();
}
Now, valid values are:
3.5f
42
0
-5
And to pass no value at all:
boost::none
If you want to keep the ref-to-non-const, you'd do something like:
boost::optional<float> myValue = 3; // or 42, or 5.1, or boost::none
doSomething(myValue);
boost::optional was nearly std::optional as of C++14, but is now part of the Library Fundamentals TS that we hope will make it, in entirety, into C++17.
Adding my 2 cents here.
You could also use pointers directly, and send nullptr for parameters that you do not want to send values for. This is, in case you do not want to include Boost for a minor feature.
Also you cannot check references for nullptr. They are supposed to have a proper address by default.

In C++, is "return;" the same thing as "return NULL;"?

my question is return; the same as return NULL; in C++?
I understand that in C++, return NULL; is the same as return 0; in the context of pointers. Obviously for integers, this is not the case as NULL cannot be added, subtracted, etc. And that it is encouraged by some to use 0 instead of NULL for pointers because it is more convenient for portability. I'm curious if this is another instance where an equivalence occurs.
I suspect that they are equivalent because return; is saying return 'nothing' and NULL is 'nothing.' However, if someone can either confirm or deny this (with explanation, of course), I would be very grateful!
is return; the same as return NULL; in C++?
No.
return is used to "break" out from a function that has no return value, i.e. a return type of void.
return NULL returns the value NULL, and the return type of the function it's found in must be compatible with NULL.
I understand that in C++, return NULL; is the same as return 0; in the context of pointers.
Sort of. NULL may not be equivalent to 0, but it will at least convert to something that is.
Obviously for integers, this is not the case as NULL cannot be added, subtracted, etc.
You can perform addition and subtraction to pointers just fine. However, NULL must have integral type (4.10/1 and 18.1/4 in C++03) anyway so it's moot. NULL may very well be a macro that expands to 0 or 0UL.
Some modern compilers will at least warn you if it was actually NULL you wrote, though.
And that it is encouraged by some to use 0 instead of NULL for pointers because it is more convenient for portability. I'm curious if this is another instance where an equivalence occurs.
No. And I disagree with this advice. Though I can see where it's coming from, since NULL's exact definition varies across implementations, using NULL will make it much easier to replace with nullptr when you switch to C++11, and if nothing else is self-documenting.
return with no expression works only if your function is declared void, in a constructor, or in a destructor. If you try to return nothing from a function that returns an int, a double, etc., your program will not compile:
error: return-statement with no value, in function returning ‘int’
According to §6.6.3/2 of C++11:
A return statement with neither an expression nor a braced-init-list can be used only in functions that do not return a value, that is, a function with the return type void, a constructor (12.1), or a destructor (12.4).
(thanks sftrabbit for the excellent comment).
return, return 0 and return NULL are not the same.
return is only valid with functions returning void, e.g.:
void func(...);
return 0 is for functions returning some int type, e.g.:
unsigned long func(...);
although it works with floating point types as well:
double func(...) { ... return 0; }
return NULL is for functions returning some pointer type, e.g.:
Something *func(...);
It works like a void function, where the return will simply exit the function and return nothing at all. This has been asked before.
There is a difference in the resulting machine code:
return will just put the instruction pointer back to where the caller came from.
return 0 or return NULL will put 0 on the stack, and then put the instruction pointer back to where the caller came from. (In C, NULL is usually mapped to 0, although that can (may?) differ in different implementations. In C++, NULL is not supposed to be used).
const testNullParity = () => {
return null
}
const testNullParity2 = () => {
return
}
console.log(testNullParity()) //null
console.log(testNullParity2()) //undefined
in javascript, return is short for return undefined as null and undefined are two different types, but they are loosely equal ie. testNullParity() == testNullParity2() is true but not testNullParity() === testNullParity2()

double as true / false

Bjarne suggests using the condition in if's as scope restriction. In particular this example.
if ( double d = fd() ) {
// d in scope here...
}
I'm curios how to interpret the declaration in a true / false sense.
It's a declaration
It's a double.
Edit:
It's in 6.3.2.1 The C++ programming language as a recommendation.
Edit2: templatetypedefs suggestion of pointers, in particular with dynamic casts, might give insight to Bjarnes suggestion.
SteveJessop tells me: - A condition is not an expression it can also be a declaration, the value used, is the value being evaluated.
The code that you're seeing is a specialized technique for declaring variables in if statements. You commonly see something like this:
if (T* ptr = function()) {
/* ptr is non-NULL, do something with it here */
} else {
/* ptr is NULL, and moreover is out of scope and can't be used here. */
}
A particularly common case is the use of dynamic_cast here:
if (Derived* dPtr = dynamic_cast<Derived*>(basePtr)) {
/* basePtr really points at a Derived, so use dPtr as a pointer to it. */
} else {
/* basePtr doesn't point at a Derived, but we can't use dPtr here anyway. */
}
What's happening in your case is that you're declaring a double inside the if statement. C++ automatically interprets any nonzero value as true and any zero value as false. What this code means is "declare d and set it equal to fd(). If it is nonzero, then execute the if statement."
That said, this is a Very Bad Idea because doubles are subject to all sorts of rounding errors that prevent them from being 0 in most cases. This code will almost certainly execute the body of the if statement unless function is very well-behaved.
Hope this helps!
In the example Stroustrup gives, the code in the if block divides a value by d:
if (double d = prim(true)) {
left /= d;
break;
}
Division by 0 is undefined behavior, so it makes some sense in this case to test d against the value 0.0 before dividing. Putting the definition in the condition is a convenient way to do this, for the reasons Stroustrup states.
Your code gives no reason why the value 0.0 would be special, and therefore it is not clear why anyone would combine the definition of d with that test. Only use Stroustrup's pattern when "false" values of the type you're defining need to be treated specially. Otherwise just do this:
{
double d = fd();
// d in scope here...
}
It is both a declaration and a double. This is quite equivalent to
{
double d = fd();
if (d) {
}
}
However, this pattern is worth the small additional syntax to simplify, as it is fairly useful and common. In addition, the transformation is less obvious once you start adding else clauses, as d is out of scope for them.
Also, as others have noted, it's useful in general but FP types in specific have some issues when compared against 0.
the if statement predicates on the value that is assigned to the variable in the assignment expression. If the double evaluates to anything but 0.0 it will run the code inside.
Note that you are not supposed to compare doubles with zero, but it generally works in my experience.
Basically, you shouldn't do this.
The other contributors to this topic have found that this expression is used to exclude the zero case so as to avoid a divide-by-zero. That's definitely smart and such a situation legitimizes this usage as far as I'm concerned (but do consider the confusion such code may cause).

C++ - Method that takes a pointer but receives an int

I am wondering how would I deal with a call to a function when an integer is passed into a function that accepts a pointer? In my case hasPlayedInTeam() accepts a pointer to Team, however, received an int. This causes the Q_ASSERT to hang.
In addition, is my problem also known as a null pointer? My professor has used that term several times in lecture, but I am not sure what he was referring to.
//main.cpp
Person p1("Jack", 22, "UCLA");
Q_ASSERT(p1.hasPlayedInTeam(0) == false);
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
bool temp = false;
foreach (Team* team, teamList) {
if (team->getName() == pTeam->getName() {
temp = true;
}
}
return temp;
}
In your call:
p1.hasPlayedInTeam(0)
the integer literal 0 is converted to a NULL pointer. So, you are not actually "receiving" an integer; you are passing an integer, the compiler can automatically cast it to the null pointer (given the definition for NULL).
I think you can fix the definition of hasPlayedInTeam by either asserting that its argument is not NULL, or by returning a default value when NULL is passed in:
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
assert(pTeam!=NULL); //-- in this case, your program will assert and halt
or:
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
if (pTeam == NULL)
return false; //-- in this case, your program will not assert and continue with a sensible (it actually depends on how you define "sensible") return value
Yes, it sounds like your problem is a null pointer. A null pointer means that you have a pointer which isn't actually pointing to anything:
Team* team = NULL;
It so happens that in C++ NULL is a macro for the integer 0. Stroustrup has some comments on which one he prefers to use in code.
Function hasPlayedInTeam() looks for the argument of type "Team" whereas you are passing the argument of type "integer" which is wrong....
Yes, I think that you are referring to a null pointer in that situation.
To treat the case when an int is passed, you can overload the function and make it behave as you want it to do, when an int is passed.
In C++ there is NULL which is defined as 0 (in some standard header file, cstddef I think) so yes the integer you are passing is the null pointer. 0 is the only (as far as I know) integer that will automatically (implicitly) be converted to a pointer of whatever type is needed.
In practice, I think most people prefer to use NULL instead of 0 for the null pointer.
I'm not sure why it is hanging however, dereferencing the NULL pointer (in your statement pTeam->getName()) should cause the program to crash if you pass it NULL, not just hang.
Unfortunately the null pointer literal is one of the confused parts of the language. Let me try to recap:
For any type there is the concept of "pointer to that type". For example you can have integers and pointer to integers (int x; int *y;), doubles and pointer to doubles (double x; double *y;), Person and pointer to Person (Person x,*y;). If X is a type then "pointer to X" is a type itself and therefore you can even find pointers to pointers to integers (int **x;) or pointers to pointers to pointers to chars (char ***x;).
For any pointer type there is a null pointer value. It's a value that doesn't really point to an object, so it's an error to try to dereference it ("dereferencing" a pointer means reading or writing the object that is being pointed to). Note that the C++ language doesn't guarantee that you will get a message or a crash when you use a null pointer to get try to get to a non-existent pointed object but just that you should not do it in a program because consequences are unpredictable. The language simply assumes you are not going to do this kind of error.
How is the null pointer expressed in a program? Here comes the tricky part. For reasons that are beyond comprehension the C++ language uses a strange rule: if you get any constant integer expression with value zero then that can be (if needed) considered to be a null pointer for any type.
The last rule is extremely strange and illogical and for example means that
char *x = 0; // x is a pointer to char with the null pointer value (ok)
char *y = (1-1); // exactly the same (what??)
char *z = !! !! !! !! !! !!
!!! !! !! !! !! !!
!!!! !! !! !! !! !!
!! !! !! !! !! !! !!
!! !!!! !! !! !! !!
!! !!! !! !! !! !!
!! !! !!!!!! !!!!!!! !!!!!!1; // Same again (!)
and this is true for any pointer type.
Why is the standard mandating that any expression and not just a zero literal can be considered the null pointer value? Really no idea.
Apparently Stroustrup also found the thing amusing instead of disgusting like it should be (the last example with the "NULL" text written with an odd number of negations is present on "The C++ Programming Language" book).
Also note that there is a NULL symbol defined in standard headers that provide a valid definition for a null pointer value for any type. In "C" a valid definition could have been (void *)0 but this is not valid in C++ because void pointers cannot be converted implicitly to other pointer types like they do in "C".
Note also that you may find in literature the term NUL (only one L) but this is the ASCII character with code 0 (represented in C/C++ with '\0') and is a logically distinct thing from a pointer or an integer number.
Unfortunately in C++ characters are integers too and therefore for example '\0' is a valid null pointer value and the same goes for ('A'-'A') (they are integer constant expressions evaluating to zero).
C++11 increases complexity of these already questionable rules with std::nullptr_t and nullptr. I cannot explain those rules because I didn't understand them myself (and I'm not yet 100% sure I want to understand them).

In C++ what causes an assignment to evaluate as true or false when used in a control structure?

So can someone help me grasp all the (or most of the relevant) situations of an assignment inside something like an if(...) or while(...), etc?
What I mean is like:
if(a = b)
or
while(a = &c)
{
}
etc...
When will it evaluate as true, and when will it evaluate as false? Does this change at all depending on the types used in the assignment? What about when there are pointers involved?
Thanks.
In C++ an attribution evaluates to the value being attributed:
int c = 5; // evaluates to 5, as you can see if you print it out
float pi = CalculatePi(); // evaluates to the result
// of the call to the CalculatePi function
So, you statements:
if (a = b) { }
while (a = &c) { }
are roughly equivalent to:
a = b
if (b) { }
a = &c
while (&c) { }
which are the same as
a = b
if (a) { }
a = &c
while (a) { }
And what about those if (a) etc when they are not booleans? Well, if they are integers, 0 is false, the rest is true. This (one "zero" value -> false, the rest -> true) usually holds, but you should really refer to a C++ reference to be sure (however note that writting if (a == 0) is not much more difficult than if (!a), being much simpler to the reader).
Anyways, you should always avoid side-effects that obscure your code.
You should never need to do if (a = b): you can achieve exactly the same thing in other ways that are more clear and that won't look like a mistake (if I read a code like if (a = b) the first thing that comes to my mind is that the developper who wrote that made a mistake; the second, if I triple-check that it is correct, is that I hate him! :-)
Good luck
An assignment "operation" also returns a value. It is the type and value of the expression. If handled by an if type statement:
while (expr)
do ... until (expr)
if (expr)
or the ternary operator (expr) ? (true value) : false value
expr is evaluated. If it is nonzero, it is true. If zero, it is false.
The return type of the assignment is the left hand value, it's what allows statements like a = b = c to compile. In your example:
while(a = &c)
{
}
Returns true when "a" is true, after it has been assigned the value of &c.
In both examples you listed, inside the parentheses is evaluated to true if a is non-zero after the assignment.
In a more common case, you compare a variable with a constant, to avoid this problem, some coding standards require that you write the constant first.
if (A_CONSTANT = var_a)
this would be caught by the compiler, whereas,
if (var_a = A_CONSTANT)
won't.
An assignment statement evaluates to the new value of the variable assigned to (barring bizarre overloads of operator=). If the assignment happens in a boolean context it will then depend on the type of that value how it is treated. If the value is a bool, it is of course treated as a bool. If the value is a numeric value, a non-zero value is treated as true. If the value is a pointer, a non-NULL value is treated as true. If it is a object, the compiler will attempt to convert it to a boolean value (e.g. operator bool). If that is not possible, the compiler will attempt to convert the object to a value that is convertible to bool (e.g. a pointer type, or a numeric type such as int). Finally, if there is no conversion to be performed, or there are multiple possible conversions (e.g. the object defines operator int and operator foo*), the code will fail to compile.
if (a = b)
...
is the shorthand for:
a = b;
if (a != 0)
...
In a while statement, assignment within the condition enables the DRY principle:
while (a = b)
{
...
}
is shorthand for (notice how I had to replicate the assignment so that it is done right before the condition check):
a = b;
while (a != 0)
{
...
a = b;
}
That said, one classic issue with code like this is knowing whether the code intended to do an assignment or if the code forget an '=' when the intent was to write '==' (i.e. should that have been while (a == b).
Because of this, you should never write just a plain assignment (gcc will issue a warning such as "suggest parentheses around assignment used as truth value"). If you want to use assignment in a control structure, you should always surround it with extra parentheses and explicitly add the not-equal:
if ((a = b) != 0)
...
while ((a = b) != 0)
...