c ++中char和signed char之间的区别?

时间:2013-05-12 01:38:35

标签: c++ c++11 char signed typetraits

请考虑以下代码:

#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 

这意味着intsigned int被视为相同类型,但不是charsigned char。那是为什么?

如果我可以使用charsigned char转换为make_signed,如何做相反的事情(将signed char转换为char)?< / p>

5 个答案:

答案 0 :(得分:17)

按设计,C++ standardcharsigned charunsigned char是不同的类型。我认为你可以使用静态转换进行转换。

答案 1 :(得分:16)

三种不同的基本字符类型: char,signed char unsigned char 。 虽然有三种字符类型,但只有两种表示形式:有符号和无符号。 (普通) char 使用其中一种表示形式。其他两个字符表示中的哪一个等同于 char 取决于编译器

在无符号类型中,所有位代表值。例如,8位 unsigned char 可以保存0到255之间的值。

标准没有定义如何表示签名类型,但是指定范围应该在正值和负值之间平均分配。因此,保证8位签名字符能够保存-127到127之间的值。

那么如何决定使用哪种类型?

使用 char 进行计算通常会产生问题。默认情况下, Char 在某些计算机上签名,在其他计算机上签名。所以我们不应该在算术表达式中使用(plain) char 。仅用于保存字符。如果您需要一个小整数,请明确指定 signed char unsigned char

答案 2 :(得分:6)

事实上,标准正在告诉char,signed char和unsigned char是3种不同的类型。 char通常是8位,但这不是标准强加的。一个8位数字可以编码256个唯一值;区别仅在于如何解释这256个唯一值。如果将8位值视为带符号二进制值,则它可以表示从-128(编码为80H)到+127的整数值。如果你认为它是无符号的,它可以表示0到255的值。根据C ++标准,有符号的char保证能够保存-127到127(不是-128!)的值,而unsigned char能够保存值0到255.

将char转换为int时,结果是实现定义的!结果可能是例如根据单一字符'''(ISO 8859-1)的机器实现,为-55或201。实际上,一个字(16位)保存字符的CPU可以存储FFC9或00C9或C900,甚至C9FF(在大端和小端表示中)。使用signed或unsigned char确保char转换为int转换结果。

答案 3 :(得分:0)

添加有关范围的更多信息:从c ++ 20开始,带符号的字符也保证了-128的值:P1236R0: Alternative Wording for P0907R4 Signed Integers are Two's Complement

对于有符号整数类型的每个值x,都有一个对应的无符号整数类型的唯一值y,以使x与y模2N相等,反之亦然;每个这样的x和y具有相同的表示。

[脚注:这也称为two's complement representation]。
[示例:带符号类型的值-1与对应的无符号类型的值2N-1相等;这些值的表示形式相同。 ]

表X中指定了实现所需的每种有符号整数类型的范围指数的最小值。

(自SO does not support markdown for table起,我恳切而痛苦地重写了下面的表x:

╔═════════════╦════════════════════════════╗  
║ Type        ║ Minimum range exponent N   ║  
╠═════════════╬════════════════════════════╣  
║ signed char ║        8                   ║  
║ short       ║       16                   ║  
║ int         ║       16                   ║  
║ long        ║       32                   ║  
║ long long   ║       64                   ║  
╚═════════════╩════════════════════════════╝  

因此,作为一个有符号字符,它有8位:-2 1到2 1 -1(n等于8)。

保证范围是-128至127 。因此,当涉及范围时,char和带符号的char之间没有更多区别。

我想说带符号的char可以帮助其他程序员,也有可能使编译器了解您将使用char的值执行算术。

答案 4 :(得分:0)

在对 char、signed char 和 unsigned char 之间的差异进行非常详细的审查后,我非常感激,我想知道:

它打算解决什么问题?

在 C++ 标准中需要什么来构建如此复杂的东西?

拥有一个你不确定它是否会被签名的字符有什么好处?

想逃避那个问题,我想为这样一个疯狂的解决方案贡献我的答案:

一个字符就是一个字符,它的任务是尽可能地包含一个字符。

如果我没记错的话,一个文本字符串(例如 const char *,甚至 char [])代表的是 UTF-8 编码的文本。

如果我们将这两个概念结合起来,我们就会得到一个字符必须包含最多允许的 UTF-8 字符。而且,正如我们所知,一个字符最多可以包含为一个单独的 UTF-8 字符是 0x00 到 0x7E 范围内的代码之一。在这个范围之外,UTF-8 字符由多个字符组成,为简洁起见,2、3 和 4 个字符。不仅仅是字符,这种表示应该被称为代码点。

无论是 1、2、3 还是 4 个字符,这些代码点都没有符号,实际上最左边的位用于编码 UTF-8 代码的头部并表示它包含多少字节,或者,也可以表示字符对标头进行补充,直到完成代码点。

最终,char 是否有符号并不重要,重要的是在文本字符串的上下文中如何解释 char。