Reputation: 531
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
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
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