我在Visual Studio 2017中以纯模式使用C ++。该编译器编译下面的语句而没有抱怨:
const char * AnArrayOfStrings[] = {"z1y2x3w4", "Aname"};
但是,如果我更改上述语句以指定char是有符号或无符号的,则编译器会发出 C2440 错误。例如,下面的语句是不编译:
const signed char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
const unsigned char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
我没有看到编译器在明确显示char的符号时拒绝编译语句的原因。
我的问题是:是否有充分的理由让我没有看到编译器拒绝编译这些语句?
感谢您的帮助(我在StackOverflow中进行了研究,C ++文档,我使用过谷歌,并且为了找到答案而咨询了大约十几本C / C ++书籍,但仍有一个原因让我望而却步。)< / p>
答案 0 :(得分:15)
"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")};
答案 1 :(得分:3)
如果你编译上面的代码
const signed char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
在C中使用选项-Wall
使用gcc然后它会发出以下警告
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 *
,从而使p1
和c
兼容类型。
在第三行中,p2
和c
的类型不兼容,编译器将在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 *
不兼容。