Char, неподписанный char и подписанный char как char & - PullRequest
0 голосов
/ 19 апреля 2020

Может кто-нибудь объяснить, почему я не могу пройти unsigned char a = 'g' и signed char b = 'g' на void f(char&){}, но я могу передать char c = 'g' на него? Как я понял после тридцати минут поиска в Google, это может быть вызвано приведением типа (не уверен). Но в чем проблема приведение от signed char к char, если они имеют одинаковый диапазон значений (конечно, если проблема в приведении типа).

Ответы [ 3 ]

3 голосов
/ 19 апреля 2020

Это разные типы.

Неважно, что они имеют одинаковый числовой диапазон.

Невозможно привязать ссылку к OneThing, к SomeOtherThing.

Это и есть цель системы типов: сделать ограничений в вашей программе, чтобы не допустить ошибок.

Опции:

  1. void f(const char&)

    Ссылки на const являются специальными. Когда вы передаете signed char здесь, оно автоматически преобразуется во временное char. Временные ссылки могут связываться с const ссылками. Однако какова будет цель этого, если вы не можете изменить исходное значение? Можно также просто передать по значению.

  2. void f(char)

    Это передача по значению. Теперь все, что может неявно преобразовать в char (например, signed char), будет принято, хотя исходное значение больше не будет "подключаться" в f. Кроме того, вы должны быть осторожны с тем, чтобы числовой диапазон соответствовал : при пропуске unsigned char это может быть не так.

  3. Тип punning

    Ваша область вызова может делать f(reinterpret_cast<char&>(mySignedChar)), и это будет работать, потому что есть специальные правила для псевдонимов / punning char s таким образом. Тем не менее, это хак, и (вопреки распространенному мнению) не законно для большинства других типов.

  4. Сделайте ваши типы согласованными

    Это то, что язык хочет, чтобы вы делали. Почему у вас есть функция, принимающая char, но функция, передающая signed char? Почему ваши типы не совпадают? Если это не под вашим контролем (например, разные идиомы из разных сторонних библиотек), тогда вы можете поиграть с типом-штамповкой, если действительно необходимо, хотя это должно быть последним средством.

2 голосов
/ 19 апреля 2020

почему я не могу передать беззнаковый символ a = 'g' и подписанный символ b = 'g' в пустоту f (char &) {}

Потому что unsigned char, signed char и char являются различными типами. И потому что ссылка не может быть связана с объектом неправильного типа. Даже со знаком или без знака целочисленного типа с одинаковой шириной (символьные типы являются целочисленными). Это ограничение является аспектом строгой типизации в языке и не позволяет программистам совершать ошибки, передавая объекты неправильного типа по ошибке.

Тем не менее, варианты без знака / со знаком могут быть неявно преобразованы друг в друга. Но результатом преобразования является rvalue, и неконстантная ссылка на lvalue не может быть привязана к rvalue. Ссылка const lvalue может быть связана с rvalue. В этом случае время жизни временного результата преобразования увеличивается, чтобы соответствовать времени жизни ссылки.

знаковый символ в символ, если они имеют одинаковый диапазон значений

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

но я могу передать ему char c = 'g'?

Это потому, что ссылка на тип T может быть связана с объектом типа T.

1 голос
/ 19 апреля 2020

Нет ссылки на lvalue. Это то, что вы пытаетесь.

Однако существует приведение к константному значению lvalue, поэтому, если вы попытаетесь вызвать:

void f(const char& c) {}

с signed char и unsigned char, это должно сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...