Basically I am trying to cast a part of a const char[x]
to const char[y]
, where y <= x
and the Original const char[x]
can not be accessed (in order to change it's forms to std::array
or anything else) and (it's content) should not be copied to another array or pointer.
But to simplify the problem, lets consider the simple case of casting a pointerconst char *pointer;
to an arrayconst char array[n];
. I (guess) this can be accomplished by casting the address of the pointer to address of the array by (possibly) one of the following loosely described methods:
void *voidPointer = &pointer;
static_cast<const char (*)[n]>(voidPointer);
(const char (*)[n]) &pointer;
reinterpret_cast<const char (*)[n]>(&pointer);
And then reading the content of that address.
In order to test these cases of casting a pointer to an array , I ran the following code:
const char string[] = "123";
const char *pointer = string;
const char **pointerAddress = &pointer;
typedef const char array_type[sizeof(string) / sizeof(char)];
typedef array_type *arrayPointer_type;
void *voidPointer = pointerAddress;
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type) pointerAddress;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointerAddress);
for(const arrayPointer_type& element : arrayPointer)
{
const char *array = *element;
bool sameValue = true;
bool sameAddress = true;
for(size_t idx = (sizeof(string) / sizeof(char)) - 1; idx--;) {
std::cout << "idx[" << idx << "]" << "pointer[" << pointer[idx]<< "]" << "array[" << array[idx]<< "], ";
if(pointer[idx] != array[idx]) {
sameValue = false;
}
if(&pointer[idx] != &array[idx]) {
sameAddress = false;
}
}
std::cout << std::endl << "sameValue[" << sameValue << "]" << "sameAddress[" << sameAddress << "]" <<std::endl <<std::endl;
}
And I got the following result:
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
Which shows that non of the casts where correct in term of keeping(not changing) the content of string
!
I studied Casting pointer to Array (int* to int[2]) and Passing a char pointer to a function accepting a reference to a char array , but I was not able to find the correct way!
So is it OK to cast pointers to arrays in C ? if so What is the correct way to cast pointers to arrays without changing their contents, in C ?
Update:
The library that I am working on is going to be used only on a very low resourced embedded platform and is going to be compiled only with GCC.
The reason for casting a portion of the const char [x]
to const char [y]
and then passing it to another functions or methods or ... is simply conformance with my other template functions or methods or ..., which can use the extra information in order to boost the speed of a process which it's current (non-optimized) version has already failed due to lack of speed. Please also note that the types of the strings that I want to deploy are not necessarily Null-terminated.
The following method is one example of such methods:
template<size_t STRING_SIZE>
requires conceptLowSize<STRING_SIZE>
self &operator<<(const char (&string)[STRING_SIZE])
{
.
.
.
return *this;
}
I am aware of the fact that deploying template functions/methods in this way might has the overhead of program size, but in this specific case, higher speed and lower memory consumption is more preferable than lower binary size of the compiled program. Also I tried many other speed optimization solutions including compiling with -o3 option and the speed did not observably improve.
CodePudding user response:
Your variable pointer
contains the address of the first character in string
; while, pointerAddress
is a pointer to a variable containing the address of the first character in string
. Basically pointerAddress
has nothing to do with string
so
void *voidPointer = pointerAddress;
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type) pointerAddress;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointerAddress);
is all wrong in that it is all casting pointerAddress
which contains the address of some other variable. The address of string
is the address of its first character i.e. try this
void* voidPointer = const_cast<char*>(pointer);
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type)pointer;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointer);