C++ Implicit conversion from bool to string - c++

I have the following code, which compiles in Visual C++ 2012.
#include <string>
void func(std::string str)
{
}
void my_func()
{
func(false);
}
The boolean 'false' is implicity passed into the string constructor
string(const char* _Ptr)
And then the pointer is null (because false = 0). Why does this compile, and should it compile according to the C++11 standard?

MSVC is mistakenly treating false as a null pointer constant. However, according to N4140, §4.10 [conv.ptr]/1 (emphasis mine):
A null pointer constant is an integer literal with value zero
or a prvalue of type std::nullptr_t. A null pointer constant can be
converted to a pointer type; the result is the null pointer value of
that type and is distinguishable from every other value of object
pointer or function pointer type.
The wording changed a bit from C++11, and you can find that discussion here. The verdict there was that it was an error in C++11 as well.
For visibility, TartanLlama provided the definition of "integer literal" below, according to [lex.icon]/1:
An integer literal is a sequence of digits that has no period or exponent part, with optional separating single quotes that are ignored when determining its value.

Related

Is it possible to edit the value of an Address thats already known in C++ [duplicate]

In C one can have string literals in the form of
char *string = "string here";
integer literals:
uint8_t num = 5;
long literals:
long long bigNum = 90322L;
floating point literals:
float decimal = 6.3f;
Is the a way to have a pointer literal? That is a literal address to a memory space. I am doing some work on an embedded project and need to hard code a value for a DMA access. I am doing something similar to the following:
uint32_t *source = 0x08000000;
While this compiles and works correctly I get the following compiler error (I'm using a variant of GCC):
cc0144: {D} warning: a value of type "int" cannot be used to initialize an entity of type "uint32_t *"
cc0152: {D} warning: conversion of nonzero integer to pointer
Is there a correct way to do this or do I just need to accept this as a fact of C? I know I can do:
uint32_t *source = (uint32_t *)0x08000000;
But that just seems very unnecessary. What is the industry way of doing this? I am also wondering if this feature exists in C++.
In both C and C++ the only pointer literal or constant is zero. We can go to the draft C99 standard section 6.3.2.3 Pointers:
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
and:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.56)
the correct way to deal with non-zero integer constant is to use a cast.
The equivalent section from the draft C++ standard would probably be section 5.2.10 Reinterpret cast which says:
A value of integral type or enumeration type can be explicitly
converted to a pointer. A pointer converted to an integer of
sufficient size (if any such exists on the implementation) and back to
the same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined. [ Note:
Except as described in 3.7.4.3, the result of such a conversion will
not be a safely-derived pointer value. —end note ]
You need to see section 3.7.4.3 for all the details.
For the pointer literal reference you need section 2.14.7 Pointer literals which says:
The pointer literal is the keyword nullptr. It is a prvalue of type
std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is
neither a pointer type nor a pointer to member type; rather, a prvalue
of this type is a null pointer constant and can be converted to a null
pointer value or null member pointer value. See 4.10 and 4.11. —end
note ]
No, it's not. That is because literals are valid values, and the only valid pointers are addresses of objects, i.e. the result of address-of operations or of pointer arithmetic on valid pointers.
You could argue that the nullptr keyword furnishes a kind of "pointer literal"; the C++ standard calls it that. It is however the only pointer literal, and ironically it is not of pointer type.
In C++ could you do something like the following?
uint32_t * source = reinterpret_cast<uint32_t*>(0x08000000);

How to find the variable stored at an address? [duplicate]

In C one can have string literals in the form of
char *string = "string here";
integer literals:
uint8_t num = 5;
long literals:
long long bigNum = 90322L;
floating point literals:
float decimal = 6.3f;
Is the a way to have a pointer literal? That is a literal address to a memory space. I am doing some work on an embedded project and need to hard code a value for a DMA access. I am doing something similar to the following:
uint32_t *source = 0x08000000;
While this compiles and works correctly I get the following compiler error (I'm using a variant of GCC):
cc0144: {D} warning: a value of type "int" cannot be used to initialize an entity of type "uint32_t *"
cc0152: {D} warning: conversion of nonzero integer to pointer
Is there a correct way to do this or do I just need to accept this as a fact of C? I know I can do:
uint32_t *source = (uint32_t *)0x08000000;
But that just seems very unnecessary. What is the industry way of doing this? I am also wondering if this feature exists in C++.
In both C and C++ the only pointer literal or constant is zero. We can go to the draft C99 standard section 6.3.2.3 Pointers:
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
and:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.56)
the correct way to deal with non-zero integer constant is to use a cast.
The equivalent section from the draft C++ standard would probably be section 5.2.10 Reinterpret cast which says:
A value of integral type or enumeration type can be explicitly
converted to a pointer. A pointer converted to an integer of
sufficient size (if any such exists on the implementation) and back to
the same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined. [ Note:
Except as described in 3.7.4.3, the result of such a conversion will
not be a safely-derived pointer value. —end note ]
You need to see section 3.7.4.3 for all the details.
For the pointer literal reference you need section 2.14.7 Pointer literals which says:
The pointer literal is the keyword nullptr. It is a prvalue of type
std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is
neither a pointer type nor a pointer to member type; rather, a prvalue
of this type is a null pointer constant and can be converted to a null
pointer value or null member pointer value. See 4.10 and 4.11. —end
note ]
No, it's not. That is because literals are valid values, and the only valid pointers are addresses of objects, i.e. the result of address-of operations or of pointer arithmetic on valid pointers.
You could argue that the nullptr keyword furnishes a kind of "pointer literal"; the C++ standard calls it that. It is however the only pointer literal, and ironically it is not of pointer type.
In C++ could you do something like the following?
uint32_t * source = reinterpret_cast<uint32_t*>(0x08000000);

Comparison between pointer and null character legal?

Is comparing a pointer to '\0' legal?
On the trunk version of clang++ (25836be2c)
const char *a = "foo";
if(a == '\0')
gives an error: comparison between pointer and integer ('const char *' and 'int')
whereas
if(a == 0)
does not give any error as expected.
Isn't the null character equivalent to the null pointer for comparisons with pointer? Is this a compiler bug?
Another point is that this error does not show up with "-std=c++03" flag but shows up with "-std=c++11" flag. However, I don't get the error in both standards when I use g++ (v4.8.5)
This was a change from C++03 to C++14. In C++03, [conv.ptr]p1 says:
A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero.
A character literal is an integral constant expression.
In C++14, [conv.ptr]p1 says:
A null pointer constant is an integer literal with value zero or a prvalue of type std::nullptr_t.
A character literal is not an integer literal, nor of type std::nullptr_t.
The originally published version of C++11 didn't contain this change; however, it was introduced due to defect report DR903 and incorporated into the standard sometime after January 2013 (the date of the last comment on that DR).
Because the change is the result of a DR, compilers treat it as a bugfix to the existing standard, not part of the next one, and so Clang and GCC both made the behavior change when -std=c++11, not just when -std=c++14. However, apparently this change wasn't implemented in GCC until after version 4.8. (Specifically, it seems to have only been implemented in GCC 7 and up.)
From [conv.ptr]§1:
A null pointer constant is an integer literal with value zero or a prvalue of type std​::​nullptr_­t. [...]
'\0' is not an integer literal, it's a character literal, thus the conversion does not apply.

Is it possible to have a pointer literal?

In C one can have string literals in the form of
char *string = "string here";
integer literals:
uint8_t num = 5;
long literals:
long long bigNum = 90322L;
floating point literals:
float decimal = 6.3f;
Is the a way to have a pointer literal? That is a literal address to a memory space. I am doing some work on an embedded project and need to hard code a value for a DMA access. I am doing something similar to the following:
uint32_t *source = 0x08000000;
While this compiles and works correctly I get the following compiler error (I'm using a variant of GCC):
cc0144: {D} warning: a value of type "int" cannot be used to initialize an entity of type "uint32_t *"
cc0152: {D} warning: conversion of nonzero integer to pointer
Is there a correct way to do this or do I just need to accept this as a fact of C? I know I can do:
uint32_t *source = (uint32_t *)0x08000000;
But that just seems very unnecessary. What is the industry way of doing this? I am also wondering if this feature exists in C++.
In both C and C++ the only pointer literal or constant is zero. We can go to the draft C99 standard section 6.3.2.3 Pointers:
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
and:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.56)
the correct way to deal with non-zero integer constant is to use a cast.
The equivalent section from the draft C++ standard would probably be section 5.2.10 Reinterpret cast which says:
A value of integral type or enumeration type can be explicitly
converted to a pointer. A pointer converted to an integer of
sufficient size (if any such exists on the implementation) and back to
the same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined. [ Note:
Except as described in 3.7.4.3, the result of such a conversion will
not be a safely-derived pointer value. —end note ]
You need to see section 3.7.4.3 for all the details.
For the pointer literal reference you need section 2.14.7 Pointer literals which says:
The pointer literal is the keyword nullptr. It is a prvalue of type
std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is
neither a pointer type nor a pointer to member type; rather, a prvalue
of this type is a null pointer constant and can be converted to a null
pointer value or null member pointer value. See 4.10 and 4.11. —end
note ]
No, it's not. That is because literals are valid values, and the only valid pointers are addresses of objects, i.e. the result of address-of operations or of pointer arithmetic on valid pointers.
You could argue that the nullptr keyword furnishes a kind of "pointer literal"; the C++ standard calls it that. It is however the only pointer literal, and ironically it is not of pointer type.
In C++ could you do something like the following?
uint32_t * source = reinterpret_cast<uint32_t*>(0x08000000);

Why is it okay to compare a pointer with '\0'? (but not 'A')

I found a bug in my code where I compared the pointer with '\0'.
Wondering why the compiler didn't warn me about this bug I tried the following.
#include <cassert>
struct Foo
{
char bar[5];
};
int main()
{
Foo f;
Foo* p = &f;
p->bar[0] = '\0';
assert(p->bar == '\0'); // #1. I forgot [] Now, comparing pointer with NULL and fails.
assert(p->bar == 'A'); // #2. error: ISO C++ forbids comparison between pointer and integer
assert(p->bar[0] == '\0'); // #3. What I intended, PASSES
return 0;
}
What is special about '\0' which makes #1 legal and #2 illegal?
Please add a reference or quotation to your answer.
What makes it legal and well defined is the fact that '\0' is a null pointer constant so it can be converted to any pointer type to make a null pointer value.
ISO/IEC 14882:2011 4.10 [conv.ptr] / 1:
A null pointer constant is an integral constant expression prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion.
'\0' meets the requirements of "integral constant expression prvalue of integer type that evaluates to zero" because char is an integer type and \0 has the value zero.
Other integers can only be explicitly converted to a pointer type via a reinterpret_cast and the result is only meaningful if the integer was the result of converting a valid pointer to an integer type of sufficient size.
'\0' is simply a different way of writing 0. I would guess that this is legal comparing pointers to 0 makes sense, no matter how you wrote the 0, while there is almost never any valid meaning to comparing a pointer to any other non-pointer type.
This is a design error of C++. The rule says that any integer constant expression with value zero can be considered as the null pointer constant.
This idiotic highly questionable decision allows to use as null pointer '\0' (as you found) but also things like (1==2) or even !!!!!!!!!!!1 (an example similar to one that is present on "The C++ programming language", no idea if Stroustrup thinks this is indeed a "cool" feature).
This ambiguity IMO even creates a loophole in the syntax definition when mixed with ternary operator semantic and implicit conversions rules: I remember finding a case in which out of three compilers one was not compiling and the other two were compiling with different semantic ... and after wasting a day on reading the standard and asking experts on c.c.l.c++.m I was not able to decide which of the three compilers was right.