I'm using native C++ with Visual Studio 2019 16.11.8. I don't understand this: whis can the false keyword be used as NULL (or nullptr)? Below the test code:
bool test(bool* pb)
{
if (NULL != pb)
return *pb;
else
return false;
}
void main()
{
test(false); // compiles (not what I was expecting)
test(true); // won't compile: error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'
}
I have tried online compilers tool, and they do not accept the
test(false);
line, which sounds to me what the normal behavior should be.
In addition, this behavior can cause issues with overloaded methods. ie, you have a test(bool* pb) method and an overloaded version with a pointer: test(int* pv)
bool test(bool* pb)
{
if (NULL != pb)
return *pb;
else
return false;
}
bool test(int* pb)
{
if (NULL != pb)
return true;
else
return false;
}
void main()
{
test(false); // won't compile anymore: error C2668: 'test' : ambiguous call to overloaded function
test(true); // won't compile: error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'
}
BTW I'm also using VS2012, which has the same behavior with the same test codes.
MSVC treats the expression false
as a null pointer constant .
A null pointer constant can be implicitly converted to any pointer type, resulting in a null pointer value.
The correct behavior according to the standard is to treat only integer literals with value 0
as null pointer constants. Although it has value 0
, false
is not an integer literal.
However this rule is only in place since resolution of CWG issue 903 . Before that every integral constant expression with value 0
was a null pointer constant.
MSVC is not implementing the defect report with default flags and still follows this old rule, according to which the expression false
is a null pointer constant.
If you give MSVC the flag /permissive-
to make it behave more standard-conform and implement the new rule. With /std:c++20
or higher this is also set by default, if I am not mistaken.
Note however, that you still have this problem if you use a literal 0
in your code and yes, it can affect overload resolution.
Values other than 0
, even if an integer literal, are never null pointer constants and therefore cannot be converted to pointers implicitly. This also applies to true
which has value 1
. Therefore overload resolution may be affected by the specific value passed as argument.
Null pointer constants are what makes NULL
work to initialize and compare null pointers, by having NULL
expand either to an integer literal with value 0
or to nullptr
. The latter is, since C++11, an alternative null pointer constant.
It is not bug. test function has like parameter pointer. false == 0 == NULL. You can have a NULL pointer. But true = 1. You cann not transform 1 (bool or int) to pointer.
Change it to:
bool test(int& pb)
{
if (pb)
return true;
else
return false;
}
An pb != NULL
or pb != false
is OK, but better is if(pb)
Your intention is to test a boolean value and an integer value by passing pointers to these values to test functions. However, when you call the test functions ( pb
and pv
) you are inadvertently not providing pointers to these values.
test(false); // error C2668: 'test' : ambiguous call to overloaded function
test(true); // error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'
In C and C++ type promotion will allow false
to be treated as NULL (nullptr) because false
is valued as 0. This will not be allowed for true
because true is valued as 1.
The first error is due to the compiler not being able to decide which test()
you want to call (because you are passing nullptr (a so called null pointer constant type ) in both cases.
The second error is due to the compiler not allowing you to convert the parameter to a pointer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.