Home > Net >  Cast an array of strings to an array of char*
Cast an array of strings to an array of char*

Time:05-10

I'm trying to get rid of the ISO C forbids converting a string constant to ‘char*’ warning, my code looks like the following:

char* var[] = {"abc", "def"};
// many more lines like this ...

One solution is to prepend each string literal with (char*) however that's ugly and unmaintainable. Ideally I'd like to be able to edit these lines to say

char* var[] = array_cast<char*>({"abc", "def"});

I found a solution here for almost the same problem except it deals with std::array instead of plain C arrays and array variables rather than initializer lists.

I want to avoid using std::array, std::string, const char*, std::vector since the functions that eventually get called accept non-const char**.

CodePudding user response:

C string literals are constant and will be placed in the .data section and protected from being modified by the hardware. No amount of casting will fix that.

C strings (std::string) are mutable so use those:

#include <string>
using namespace std::literals;

std::string var[] = {"abc"s, "def"s};

Although why you would want mutable strings in an array escapes me.

CodePudding user response:

"abc" and "def" are string literals of type const char[4] which decays to const char*(and not char*) due to type decay.

So you need to add a low-level const indicating that var is an array of pointers to const char(instead of pointer to char) as shown below:

const char* var[] = {"abc", "def"};

Or better yet use std::array or std::vector with elements of type std::string.

std::vector<std::string> var{"abc", "def"};

CodePudding user response:

As a possible workaround, it would be possible to use two arrays, one with std::string objects, and one with char* pointers to the strings in the first array:

std::array<std::string, 2> real_strings = {{ "foo", "bar" }};
char* wrap[] = { &real_strings[0][0], &real_strings[1][0] };

This can of course be used together with a vector and dynamic allocation and a loop to initialize the wrapper array, if the number of strings is not known at compile-time (or may change at run-time).


On a personal note, to me it all seems like a design flaw in the API you're using.

CodePudding user response:

I have arrived at a solution. It requires two arrays one of which needs to be cleaned up afterwards so it can surely be improved.

template<size_t N, size_t... Is>
constexpr char** 
array_cast(const std::array<const char*, N>& arr, std::index_sequence<Is...>)
{
   return new char*[]{const_cast<char*>(std::get<Is>(arr))...};
}

template<size_t N>
constexpr char**
array_cast(const std::array<const char*, N>& arr)
{
   return array_cast(arr, std::make_index_sequence<N>());
}

const std::array var {"abc", "def"};

char** result = array_cast(var);

CodePudding user response:

You can create a modifiable 2d array of chars like this:

char var[][4] = {"abc", "def"};
  •  Tags:  
  • c
  • Related