ScienceAmateur
ScienceAmateur

Reputation: 531

Why doesn't C++ accept signed or unsigned char for arrays of characters

I am using C++ in native mode with Visual Studio 2017. That compiler compiles the statement below without complaint:

const char * AnArrayOfStrings[]  = {"z1y2x3w4", "Aname"};

However, if I change the above statement to specify that char is signed or unsigned, the compiler emits a C2440 error. For instance, the statements below, do not compile:

const signed   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};

const unsigned char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};

I fail to see the reason for the compiler refusing to compile the statement when the sign of char is made explicit.

My question is: is there a good reason that I have failed to see for the compiler refusing to compile those statements ?

Thank you for your help (I did research in StackOverflow, the C++ documentation, I used Google and, consulted about a dozen C/C++ books in an effort to find the answer myself but, a reason still eludes me.)

Upvotes: 21

Views: 3744

Answers (2)

haccks
haccks

Reputation: 106122

If you compile the above code

const signed   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};  

in C with gcc using options -Wall then it will give the following warning

test.c:5:49: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
  const unsigned   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
                                                 ^
test.c:5:49: note: (near initialization for 'AnArrayOfStrings2[0]')
test.c:5:61: warning: pointer targets in initialization differ in signedness [-Wpointer-sign]
  const unsigned   char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};  

The type of elements of AnArrayOfStrings2 and "z1y2x3w4" are different. AnArrayOfStrings2[0] is of type const signed char * while "z1y2x3w4" is of type const char[9].
The same code will raise error in C++. You will need explicit cast to make it work in C++.


To explain why

const char * AnArrayOfStrings[]  = {"z1y2x3w4", "Aname"}; 

works I will take s simple example

const char c[] = "asc";
const char *p1 = c;           // OK
signed const char *p2 = c;    // Error
unsigned const char *p3 = c;  // Error

In the second line of the above snippet, c will convert to const char * thus making p1 and c compatible types.
In third line the type of p2 and c are incompatible and compiler will raise an error in C++ (a warning in C). Same will happen with line 4.

If we take another example for int type

const int i[] = {1,2,3};
const int *ii = i            // OK
signed const int *si = i;    // OK
unsigned const int *usi = i; // Error  

First two pointer initializations work as int without any specifier is equivalent to signed int (but this is not true with char) and therefore types are compatible. Intialization fails in last case as const int * or signed const int * is incompatible with unsigned const int *.

Upvotes: 3

Gaurav Sehgal
Gaurav Sehgal

Reputation: 7542

"z1y2x3w4" is const char[9] and there is no implicit conversion from const char* to const signed char*.

You could use reinterpret_cast

const signed char * AnArrayOfStrings[]  = {reinterpret_cast<const signed char *>("z1y2x3w4"),
                                           reinterpret_cast<const signed char *>("Aname")};

Upvotes: 15

Related Questions