已签名和未签名的char数据类型

4
为什么两个值相同的字符,如signed charunsigned char不相等?
char a = 0xfb; 
unsigned char b = 0xfb;
bool f;
f = (a == b); 
cout << f;

在上面的代码中,f 的值是0。
为什么当 ab 的值相同时会出现这种情况呢?

我的代码运行时没有任何警告,并且输出为0。 - T.g
@raymondChen a 是 -5 -> a 很可能是-5 - Bathsheba
1
@Bathsheba 我认为深入探讨编程语言细节对于帮助问题提出者并没有太大意义。我们应该尝试解释观察到的行为。 - Raymond Chen
CHAR_MAX 不等于 127 且整数不是二进制补码的系统数量基本上为零。没有必要在初学者讨论中引入这种可能性。 - Raymond Chen
2
@RaymondChen:胡说八道。在这里提供一系列答案是合适的。我真的看不出你的观点。不要(i)对OP做出假设,也不要(ii)假设整个页面都是针对OP的。而且你上面的评论是无知的。我可以访问一个机器,其中char、short、int、long和long long都是相同大小的。 - Bathsheba
显示剩余6条评论
3个回答

8

没有算术运算符接受小于int的整数。因此,两个char值首先被提升为int,详见整数提升

在您的平台上,char是有符号的,因此0xfb被提升为int(-5),而unsigned char被提升为int(0x000000fb)。这两个整数不相等。

另一方面,在[basic.fundamental]中,标准要求所有char类型占用相同的存储空间并具有相同的对齐要求;也就是说,它们具有相同的对象表示形式,并且对象表示形式的所有位都参与值表示。因此,memcmp(&a, &b, 1) == 0true


6
f 的值,实际上整个程序的运行结果是由具体实现定义的。
在 C++14 中(及以后版本),对于一个有符号char, 假设 CHAR_MAX127,那么 a 可能是 -5。严格来说,如果 char 是有符号的并且该数字无法容纳在 char 类型中,则转换是由具体实现定义的,或引发一个由具体实现定义的信号。 b251
对于比较 a == b(保留假设 char 是一个比 int 更窄的类型),两个参数都会被转换为int,因此保留 -5251
由于这些数字不相等,因此结果是false
最后,请注意,在平台上,charshortint 都具有相同的大小时,您的代码结果将为true(并且== 将用于无符号类型)!寓意是不要混合使用不同类型
1 C++14 放弃了1的补码和符号位 signed char

为什么是-5?我是这样计算出-3的:-127 + (251 - 127)。这不正确吗? - pergy
@pergy。不,二进制补码不是这样工作的。它是-5。 - Bathsheba
(实际上,该答案使用值-5作为示例) - anatolyg
@anatolyg:嗯,你不能比那更好了! - Bathsheba
"C++14取消了1的补码和有符号幅度有符号字符。我已经检查了当前的标准草案,没有找到这个内容。这是明确说明的吗,还是可以推断出来?" - geza

4
  • (有符号)char 的取值范围为 [-128, 127]。(C++14 将 -127 作为下限取消了)。
  • unsigned char 的取值范围为 [0, 255]

你试图将值 251 赋给这两个变量。由于 char 无法存储该值,因此会出现值溢出,就像以下警告所示:

警告:从 'int' 转换到 'char' 时溢出,将值从 '251' 改为 ''\37777777773'' [-Woverflow]

因此,a 可能会保存值 -5,而 b 将是 251,它们确实不相等。


但是在输出时,a和b都打印相同的符号。 - T.g
@T.g 字符类型的打印机制解释的是底层的比特模式,而不是变量的数值。表示方式相同,但值是不同的。 - molbdnilo
@molbdnilo 谢谢,我明白了...但是由于251不在[-128,127]的范围内,所以如何将值-5赋给a? - T.g
@T.g 我刚刚在另一个答案下问了同样的问题 :) 看看这个链接:https://dev59.com/6XNA5IYBdhLWcg3wNq8y#1049880 - pergy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接