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);
Related
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);
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);
Recently I encountered code that did this:
static_assert(sizeof(void*) >= sizeof(size_t));
size_t idx = get_index_to_array();
void* ptr = (void*)idx;
Essentially using a void* pointer provided by a third party library to store an index into an array to save an allocation.
Assuming that the pointer will neither be dereferenced nor freed/deleted at any point, and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?
Asuming that the pointer will not get dereferenced nor freed/deleted at any point and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?
It is conforming.
Since there is no compatible static cast, this explicit type conversion (colloquially called C-style cast) performs a reinterpret cast. Of this, the standard says (quoting the latest draft):
[expr.reinterpret.cast]
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.
If, as you say, this void* pointer will not be used for anything but being cast back to an int, then yes, this code is fine.
The C-style cast in (void*)idx falls back to a reinterpret_cast when all other casts fail (such as static_cast). Usually reinterpret cast is a dangerous thing, but it does come with the guarantee that casting to an intermediate type, then back to the original type, will always yield the original value. Thus, your code, under the stated constraints, is fine.
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);
I have this code:
int main()
{
char buffer[10];
if( buffer ) {
return 1;
}
return 0;
}
which Visual C++ 10 interprets like this: buffer decays to a pointer, then a pointer is compared against null. When this is compiled with /O2 the check gets eliminated and the code gets equivalent to just return 1;.
Is the code above valid? Does Visual C++ compile it right (I mean the decaying part, not the optimization)?
C++11, 6.4/4:
The value of a condition that is an expression is the value of the
expression, contextually converted to bool for statements other than
switch; if that conversion is ill-formed, the program is ill-formed.
So the standard says that the compiler has to perform any implicit conversions at its disposal to convert the array to a boolean. Decaying the array to pointer and converting the pointer to boolean with a test against against equality to null is one way to do that, so yes the program is well-defined and yes it does produce the correct result -- obviously, since the array is allocated on the stack, the pointer it decays to can never be equal to the null pointer.
Update: As to why this chain of two conversions is followed:
C++11, 4.2/1:
An lvalue or rvalue of type “array of N T” or “array of unknown bound
of T” can be converted to a prvalue of type “pointer to T”. The result
is a pointer to the first element of the array.
So, the only legal conversion from an array type is to a pointer to element type. There is no choice in the first step.
C++11, 4.12/1:
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. 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
std::nullptr_t can be converted to a prvalue of type bool; the
resulting value is false.
There is an implicit conversion directly from bare pointer to boolean; so the compiler picks that as the second step because it allows the desired result (conversion to boolean) to be immediately reached.
Yes, the conversion from an array type to bool is well-defined by the standard conversions. Quoting C++11, 4/1 (with the relevant conversions highlighted):
A standard conversion sequence is a sequence of standard conversions in the following
order:
— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion,
and function-to-pointer conversion.
— Zero or one conversion from the following set: integral promotions, floating point promotion, integral
conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to
member conversions, and boolean conversions.
— Zero or one qualification conversion.
A standard conversion sequence will be applied to an expression if necessary to convert it to a required
destination type.
Yes.
if( buffer ) means: check if buffer is not NULL. An array variable points to the start of the array (unless you move it) and is equivalent to a pointer.
The optimization just returns 1 because that buffer is allocated on the stack, so it definitely has a value (pointer to the location on the stack), so it's always true.
You said it yourself :
buffer decays to a pointer
Since the array is on the stack, it can not be NULL (unless something goes wrong, like stack smashing).