Разница между char и подписанной char в С++? - программирование
Подтвердить что ты не робот

Разница между char и подписанной char в С++?

Рассмотрим следующий код:

#include <iostream>
#include <type_traits>

int main(int argc, char* argv[])
{
    std::cout<<"std::is_same<int, int>::value = "<<std::is_same<int, int>::value<<std::endl;
    std::cout<<"std::is_same<int, signed int>::value = "<<std::is_same<int, signed int>::value<<std::endl;
    std::cout<<"std::is_same<int, unsigned int>::value = "<<std::is_same<int, unsigned int>::value<<std::endl;
    std::cout<<"std::is_same<signed int, int>::value = "<<std::is_same<signed int, int>::value<<std::endl;
    std::cout<<"std::is_same<signed int, signed int>::value = "<<std::is_same<signed int, signed int>::value<<std::endl;
    std::cout<<"std::is_same<signed int, unsigned int>::value = "<<std::is_same<signed int, unsigned int>::value<<std::endl;
    std::cout<<"std::is_same<unsigned int, int>::value = "<<std::is_same<unsigned int, int>::value<<std::endl;
    std::cout<<"std::is_same<unsigned int, signed int>::value = "<<std::is_same<unsigned int, signed int>::value<<std::endl;
    std::cout<<"std::is_same<unsigned int, unsigned int>::value = "<<std::is_same<unsigned int, unsigned int>::value<<std::endl;
    std::cout<<"----"<<std::endl;
    std::cout<<"std::is_same<char, char>::value = "<<std::is_same<char, char>::value<<std::endl;
    std::cout<<"std::is_same<char, signed char>::value = "<<std::is_same<char, signed char>::value<<std::endl;
    std::cout<<"std::is_same<char, unsigned char>::value = "<<std::is_same<char, unsigned char>::value<<std::endl;
    std::cout<<"std::is_same<signed char, char>::value = "<<std::is_same<signed char, char>::value<<std::endl;
    std::cout<<"std::is_same<signed char, signed char>::value = "<<std::is_same<signed char, signed char>::value<<std::endl;
    std::cout<<"std::is_same<signed char, unsigned char>::value = "<<std::is_same<signed char, unsigned char>::value<<std::endl;
    std::cout<<"std::is_same<unsigned char, char>::value = "<<std::is_same<unsigned char, char>::value<<std::endl;
    std::cout<<"std::is_same<unsigned char, signed char>::value = "<<std::is_same<unsigned char, signed char>::value<<std::endl;
    std::cout<<"std::is_same<unsigned char, unsigned char>::value = "<<std::is_same<unsigned char, unsigned char>::value<<std::endl;
    return 0;
}

Результат:

std::is_same<int, int>::value = 1
std::is_same<int, signed int>::value = 1
std::is_same<int, unsigned int>::value = 0
std::is_same<signed int, int>::value = 1
std::is_same<signed int, signed int>::value = 1
std::is_same<signed int, unsigned int>::value = 0
std::is_same<unsigned int, int>::value = 0
std::is_same<unsigned int, signed int>::value = 0
std::is_same<unsigned int, unsigned int>::value = 1
----
std::is_same<char, char>::value = 1
std::is_same<char, signed char>::value = 0
std::is_same<char, unsigned char>::value = 0
std::is_same<signed char, char>::value = 0
std::is_same<signed char, signed char>::value = 1
std::is_same<signed char, unsigned char>::value = 0
std::is_same<unsigned char, char>::value = 0
std::is_same<unsigned char, signed char>::value = 0
std::is_same<unsigned char, unsigned char>::value = 1 

Это означает, что int и signed int рассматриваются как один и тот же тип, но не char и signed char. Почему это?

И если я могу преобразовать char в signed char с помощью make_signed, как сделать обратное (преобразовать a signed char в char)?

4b9b3361

Ответ 1

Он по дизайну стандарт С++ говорит, что char, signed char и unsigned char - разные типы. Я думаю, вы можете использовать статическую трансляцию для преобразования.

Ответ 2

Существуют три различных основных типа символов: char, подписанный char и unsigned char. Хотя существует три типа символов, существует только два представления: signed и unsigned. (Plain) char использует одно из этих представлений. Какое из двух других представлений символов эквивалентно char зависит от компилятора.

В неподписанном типе все биты представляют значение. Например, 8-разрядный без знака char может содержать значения от 0 до 255 включительно.

Стандарт не определяет, как представлены типы подписей, но указывает, что диапазон должен быть равномерно распределен между положительными и отрицательными значениями. Следовательно, 8-разрядная подписанная char гарантированно сможет хранить значения от -127 до 127.


Итак, как решить, какой тип использовать?

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

Ответ 3

Действительно, стандарт точно говорит, что char, подписанный char и unsigned char - 3 разных типа. A char обычно составляет 8 бит, но этот стандарт не накладывается. 8-разрядное число может кодировать 256 уникальных значений; разница заключается только в том, как интерпретируются эти 256 уникальных значений. Если вы считаете 8-битное значение в качестве знакового двоичного значения, оно может представлять целочисленные значения от -128 (все 1) до +127. Если вы считаете его неподписанным, он может представлять значения от 0 до 255. По стандарту С++ подписанный char гарантированно сможет хранить значения от -127 до 127 (не -128!), Тогда как unsigned char способный удерживать значения от 0 до 255.

При преобразовании char в int результат определяется реализацией! результат может, например, be -55 или 201 в соответствии с реализацией машины одиночного char 'É' (ISO 8859-1). Действительно, процессор, содержащий char в слове (16 бит), может либо хранить FFC9, либо 00C9, либо C900, или даже C9FF (в больших и маленьких представлениях). Использование подписанных или неподписанных char действительно гарантирует результат преобразования char в int.