Is it possible to have a pointer literal? - c++

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);

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);

Double pointer typecast in C++

I have below C++ code snippet which works perfectly fine:
Address = **(uint32_t **)(0x12345678);
I have a LDRA warning at the line mentioned above Use of C type cast. Can anyone please help me in type casting above instruction to C++ style?
Thanks,
Kalyan
That's a reinterpret_cast
Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.
A value of any integral or enumeration type can be converted to a pointer type. A pointer converted to an integer of sufficient size and back to the same pointer type is guaranteed to have its original value, otherwise the resulting pointer cannot be dereferenced safely (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations) The null pointer constant NULL or integer zero is not guaranteed to yield the null pointer value of the target type; static_cast or implicit conversion should be used for this purpose.
So it would be
Address = **reinterpret_cast<uint32_t **>(0x12345678);

GCC implementation for behavior of reinterpret cast

How can I know how will reinterpret cast work on GCC compiler? Is it mentioned in the documentation? May I know any reference or link if it exist?
Reading the documentation in the standard it is very explicit about different types. But for the basic pointer we have:
A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined. [ Note: It is intended to be unsurprising to those who know the addressing structure of the underlying machine. — end note ] A value of type std::nullptr_t can be converted to an integral type; the conversion has the same meaning and validity as a conversion of (void*)0 to the integral type. [Note: A reinterpret_cast cannot be used to convert a value of any type to the type std::nullptr_t. — end note ]
For integers:
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. —endnote]
I have used reinterpret_cast many times with g++. In embedded programming, it's useful for mapping a struct that represents a peripheral's registers to its (fixed) address:
struct DEV_Registers
{
volatile uint32_t REGA;
volatile uint32_t REGB;
// ...
};
static DEV_Registers& DEV(*reinterpret_cast<DEV_Registers>(0x40000000));
This lets me write code like:
DEV.REGB = 0x12345678;
which does the right thing (set the register at 0x40000004 to the value 0x12345678) and is quite legible.
It's hard to tell if your question is asking for details beyond this.

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.