为什么C++不接受字符数组的有符号或无符号字符



>我在Visual Studio 2017的本机模式下使用C++。 该编译器毫无怨言地编译了以下语句:

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

但是,如果我更改上述语句以指定 char 是有符号的还是无符号的,编译器会发出C2440错误。 例如,下面的语句编译:

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

我看不出编译器在明确字符符号时拒绝编译语句的原因。

我的问题是:是否有充分的理由让我看不到编译器拒绝编译这些语句?

感谢您的帮助(我在StackOverflow中做了研究,C++文档,我使用Google并查阅了大约十几本C/C++书籍,试图自己找到答案,但是,一个原因仍然让我无法找到答案。

>"z1y2x3w4"const char[9],并且没有从const char*const signed char*的隐式转换。

您可以使用reinterpret_cast

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

如果你编译上面的代码

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

在 C 中使用 gcc 使用选项-Wall然后它会给出以下警告

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"};  

AnArrayOfStrings2"z1y2x3w4"元素的类型不同。AnArrayOfStrings2[0]属于const signed char *型,而"z1y2x3w4"属于const char[9]型。
相同的代码将在C++中引发错误。您将需要显式强制转换才能使其在C++中工作。


解释原因

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

作品我会举一个简单的例子

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

在上述代码片段的第二行中,c将转换为const char *从而使p1c兼容的类型。
在第三行中,p2c的类型不兼容,编译器将在C++中引发错误(C 中的警告)。第 4 行也会发生同样的情况。

如果我们再举一个例子int类型

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

前两个指针初始化工作int没有任何说明符等效于signed int(但对于char不是这样),因此类型是兼容的。初始化在最后一种情况下失败,因为const int *signed const int *unsigned const int *不兼容。

最新更新