0
  • Is it possible to cast pointers to arrays in C++?
  • Is casting pointers to arrays in C++, problem free? and / or, is it considered to be a good practice?
  • If it is possible, then what is the method of casting pointers to arrays in C++? and if there are problems with doing so, then how to avoid them?

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.

AKL
  • 1,367
  • 7
  • 20
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/248141/discussion-on-question-by-akl-how-to-cast-pointers-to-arrays-in-c). – Samuel Liew Sep 17 '22 at 14:40

1 Answers1

1

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);
jwezorek
  • 8,592
  • 1
  • 29
  • 46
  • Nothing is really gained though. Using an array of pointers to elements and putting the size `3` directly into the loop instead of `(sizeof(string) / sizeof(char)) - 1` would have had the same effect. Also, accessing through the array pointers is probably technically supposed to be undefined behavior (although the standard is currently not really clear on it). – user17732522 Sep 15 '22 at 16:54
  • yeah, i mean i'm not endorsing the OP's code here as good things to put in real code just trying to explain the misunderstanding that makes the original code totally incorrect rather than just probable undefined behavior that will probably do what we expect. – jwezorek Sep 15 '22 at 16:57
  • @user17732522 I appreciate it if you could kindly reffer me to a source which mention "accessing through the array pointers is probably technically supposed to be undefined behavior" If as you mentioned "(although the standard is currently not really clear on it)" and gcc is OK with it, that is good enough for me because this library that I am working on is not supposed to be used any where else! – AKL Sep 15 '22 at 19:16
  • @jwezorek Thank you, this works and corrected my assumption about arrays!. I hastily misread the answer for the question, https://stackoverflow.com/questions/20046429/casting-pointer-to-array-int-to-int2 hence I made a mistake. Although you don't recommend this solution, I appreciate it and I will most likely use it! – AKL Sep 15 '22 at 19:16
  • @AKL The problem is that the relevant standard paragraph https://eel.is/c++draft/conv.array has some problems. It talks about "_the array_", although there is no array object introduced in the paragraph. Specifically in your case there is no array object with a length mismatching e.g. the string literal length. The paragraph is also missing obvious requirements like the type of the referenced object being similar to that of the expression type. – user17732522 Sep 15 '22 at 19:26
  • I suspect that the intent is for this to be undefined behavior because it would otherwise make optimizations based on length in functions taking arrays by-reference impossible, although I was not able to get any current compiler to make use of such an optimization (to my surprise). – user17732522 Sep 15 '22 at 19:26