Сужение преобразования от int к char внутри {} | Проблема с подписью символа - PullRequest
0 голосов
/ 06 мая 2020

См. Поведение char в случае vector<char> и автономного char:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> someInts = {2, 3, 1 + 5};
    // I can perform operations   ^^^^^   inside the braces in this case

    // vector<char> someChars = {'a', 'b', 'r' + 'z'};
    // But doing the same in case of char  ^^^^^^^^^  gives an error

    // However, it works for a standalone char
    char ch = 'r' + 'z';
    cout << ch;
    // Value^^^is '∞' as expected
}

Раскомментирование строки vector<char> дает:

Ошибка: сужение преобразования '236' из 'int' в 'char' внутри {}

Это была проблема.


Тогда я прочитал этот документацию Инициализация списка и увидел следующее, что может быть связано с этой проблемой:

Сужение преобразований

list- инициализация ограничивает допустимые неявные преобразования, запрещая следующее:

  • многие другие причины
  • преобразование из целочисленного типа или типа перечисления без области действия в целочисленный тип, который не может представляют все значения оригинала, за исключением случаев, когда источник является константным выражением, значение которого может быть сохранено точно в целевом типе

Это заставило меня понять сообщение об ошибке (я думаю) , и я изменил vector<char> на vector<unsigned char>, и это сработало:

* 1 044 *

Вывод: _a_b_∞


Итак, мой вопрос:

  1. Если подпись из char была проблема, как автономная версия char работала в этом случае? Что касается этого потока в stackoverflow, как тот же компилятор выбрал signed char для vector<char> и unsigned char для char?

  2. Если мой вывод о проблеме неверен, какова правильная причина этой проблемы?

1 Ответ

3 голосов
/ 06 мая 2020

1+5 - это int, поэтому нет проблем с его использованием для инициализации записи vector<int>.

'r' + 's' - это int (236), которое выходит за пределы char в вашей системе. Итак, - это проблема при попытке использовать его для инициализации записи vector<char>. Это именно тот случай, для которого было разработано правило об инициализации списка, запрещающее сужающие преобразования.

Вы получите ту же ошибку для vector<char> x = { 'a', 'b', 123456 };

Standalone char либо имеет те же свойства, что и signed char, либо unsigned char, который определяется реализацией, а некоторые у компиляторов есть переключатель для выбора (например, -funsigned-char на G CC). Для ясности, в любом случае это по-прежнему отдельный тип.


По вашим словам, char действительно был подписан в обоих случаях, как объяснил Натан Оливер в комментариях . Проблема в том, что у вас неправильное представление о том, что автономный char не был подписан в вашем случае. Просто потому, что char ch = 'r' + 'z'; скомпилирован, не означает, что он беззнаковый. Вы, наверное, подумали, что он беззнаковый, потому что 'r' + 'z' == 236 не подходит к signed char. Нет, он подходит к signed char по следующей причине:

char ch = 'r' + 'z'; - это преобразование вне допустимого диапазона . Начиная с C ++ 20 результатом будет -20 (при условии, что обычный char имеет 8-битную подпись, как указано в вашем предыдущем сообщении об ошибке, и система использует кодировку ASCII), до этого результат был определен реализацией.


Итак, не предполагайте ничего. Если вы не уверены, является ли char в вашей системе подписанным или неподписанным, просто отметьте CHAR_MIN.

...