[英]If char c = 0x80, why does printf(“%d\n”, c << 1) output -256?
#include<stdio.h>
int main(void)
{
char c = 0x80;
printf("%d\n", c << 1);
return 0;
}
在这种情况下,输出为-256
。 如果我写c << 0
那么输出是-128
。
我不明白这段代码背后的逻辑。
char
可以在您的平台上签名,在这种情况下, 0x80
代表-128(假设是2的补码)。
当char
被用作<<
运算符的操作数时,它被提升为int
(仍然是-128)。 所以当你应用左移时,你得到-256。 从技术上讲,转移负值是实现定义的未定义,但您看到的是典型行为。
您的出发点已经存在问题:
char c = 0x80;
如果(看似在你的情况下) char
是一个有符号的类型,你将整数常量128
一个只能保证最多值为127
。 然后,您的编译器可能会选择为您提供一些实现定义的值(在您猜测的情况下为-128
)或发出范围错误。
然后你正在对该负值进行左移。 这给出了未定义的行为。 总共有几个实现定义的选择加上确定结果的未定义行为:
char
128
转换为signed char
char
的宽度 int
的符号表示(有三种可能性) int
上实现(或不)左移的选择 查看所有这些案例可能是一个很好的练习,以了解不同的结果。
总结一些建议:
char
算术 c
被分配0x80
。 假设8位字节,其二进制表示的值为10000000
。 显然,在您的平台上, char
是签名类型。 因此, 0x80
(即10000000
)对应于-128。
当<<
应用于char
值时,它将被提升为int
并保留符号。 因此,当向左移动一次时,使用32位整数,它变为11111111111111111111111100000000
(二进制补码),即-256。
只是一个侧面说明。 从下到上的角度来看,逐位移位(和屏蔽)基于架构的字长(以位表示)。 一个词的长度因建筑而异。
如果知道目标体系结构的字长,则可以使用位移来乘法,并且比使用操作数更快地除(在某些情况下)。
由于位移代码依赖于体系结构,因此无法假设特定的位移代码将从架构到架构以相同的方式工作。 然而,一旦熟悉不同体系结构的不同字长的想法,比特移位变得不那么神秘和可预测。
值得庆幸的是,今天我们有8,16,32和64位字长,并且只有8位字符长度。 在古代计算的时代,架构可能具有12或15或23位字长(等等,令人作呕)。
我想知道为什么你的编译器不会抱怨0x80不适合char,你的平台上只能表示-0x80到0x7F的值。
试试这段代码:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main() {
printf("char can represent values from %d to %d.\n", CHAR_MIN, CHAR_MAX);
return EXIT_SUCCESS;
}
您的情况称为OVERFLOW。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.