Почему C++ не принимает подписанный или неподписанный символ для массивов символов
Я использую C++ в основном режиме с Visual Studio 2017. Этот компилятор компилирует выражение ниже без жалобы:
const char * AnArrayOfStrings[] = {"z1y2x3w4", "Aname"};
Однако, если я изменил вышеприведенный оператор, чтобы указать, что char подписан или неподписан, компилятор испускает ошибку C2440. Например, приведенные ниже утверждения не компилируются:
const signed char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
const unsigned char * AnArrayOfStrings2[] = {"z1y2x3w4", "Aname"};
Я не вижу причины, по которой компилятор отказывается компилировать инструкцию, когда знак char становится явным.
Мой вопрос: есть ли веская причина, по которой я не видел, чтобы компилятор отказался компилировать эти утверждения?
Спасибо за вашу помощь (я проводил исследования в StackOverflow, документации C++, я использовал Google и консультировался о десятках книг C/C++, пытаясь найти ответ сам, но причина по-прежнему не ускользает от меня).
Ответы
Ответ 1
"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")};
Ответ 2
Если вы скомпилируете приведенный выше код
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 *
что делает 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 *
.