在IndiaBix.com上,我遇到了以下问题。根据我的经验水平(C语言中的初学者),上面的输出应该是0 (10000000 << 1 is 00000000)
,但是在经过更深入的我发现后,它的结果为256我们使用%d 打印,支持4个字节,因此输出为256而不是0。
#include<stdio.h>
int main()
{
unsigned char i = 128;
printf("%d \n", i << 1);
return 0;
}
现在考虑以下示例
#include<stdio.h>
int main()
{
unsigned int i = 2147483648;(bit 31 = 1 and b0 to b30 are 0)
printf("%d \n", i<<1);
return 0;
}
当我离开上面时,我得到0作为输出,因为%d支持int的值,输出应该是0但是当我将%d更改为%ld时输出仍为0.因为%ld支持值长达int输出不应该是0.为什么我得到0作为输出。
答案 0 :(得分:2)
在第一种情况下,i
被提升为int
,可以存储至少32767,然后计算移位。结果,结果变为256。
在第二种情况下,如果您的unsigned int
长度为32位,则会在unsigned int
中计算,结果将会结束。结果,结果变为0。
你必须投射到更大的类型才能得到你想要的东西。
#include<stdio.h>
#include<inttypes.h>
int main()
{
unsigned int i = 2147483648;//(bit 31 = 1 and b0 to b30 are 0)
printf("%"PRIu64" \n", (uint64_t)i<<1);
return 0;
}
答案 1 :(得分:2)
此处不重要%d
或%ld
。
可能是因为机器上的大小为unsigned int ,只有4个字节。
此外,您不能将%ld
与 unsigned int 一起使用。这是未定义的行为。
答案 2 :(得分:1)
第一个问题是2147483648(80000000h)将适合您的32位无符号整数,但它不适合printf在使用int
说明符时所期望的签名%d
。相反,请使用%u
说明符。
修复后,请注意,如果unsigned int为32位,0x80000000 << 1
假设为0。
将printf
的格式说明符更改为%ld
不会更改表达式的类型!如果需要更大的类型,则需要更改两者格式说明符和表达式。
你被第一个char
印刷品的行为所欺骗。 %d
在那里工作的原因是因为printf(像任何可变函数一样)在内部将所有参数提升为至少int
的大小。因此,表达式被隐式提升为int
,并且恰好与%d
匹配。
虽然在my_char << n
的情况下,<<
运算符已经整数将两个操作数提升为int
,并且移位的结果始终具有可能提升的左操作数的类型。 / p>
正如您所知,C中的各种隐式类型提升规则并非易事,因此可以轻松地创建错误。这是该语言众多众所周知的缺陷之一。
答案 3 :(得分:0)
根据C标准(6.5.7按位移位算子)
3 对每个操作数执行整数提升。 结果的类型是提升的左操作数....
和(6.3.1.1布尔,字符和整数)
- ...如果int可以表示原始类型的所有值(按宽度限制&gt;对于位字段),该值将转换为 一个int;否则,它将转换为unsigned int。 这些是 称为整数提升 .58)所有其他类型均未更改 整数促销。
醇>
这意味着类型unsigned char
的操作数被提升为int
类型,因为类型int
可以表示unsigned char
类型的所有值。
所以在表达中
i << 1
操作数i
被提升为类型int
,你会得到(假设int类型有32
位)
0x00000080 << 1
手术后你会得到结果
0x00000100
对应十进制
256
和本声明
printf("%d \n", i << 1);
输出此结果。
现在考虑一下这段代码
unsigned int i = 2147483648;(bit 31 = 1 and b0 to b30 are 0)
printf("%d \n", i<<1);
此处i
可以表示为
0x80000000
整数提升适用于转换级别小于int类型的类型。
因此整数促销不会应用于变量i
,因为它的排名不会低于int
的等级。
操作完成后,您将获得
0x00000000
即你将得到十进制
0
和本声明
printf("%d \n", i<<1);
将正确输出此零,因为它的表示对于无符号和有符号整数对象是相同的。
即使你写了例如
printf( "%lld \n", ( long long int )( i<<1 ));
你会得到相同的结果,因为在任何情况下表达式i << 1
的类型都是unsigned int
但是如果你要写
printf( "%lld \n", ( long long int )i << 1 );
然后操作数i
将转换为long long int
类型,您将获得
0x0100000000
答案 4 :(得分:0)
将%d更改为%id无效 将数据类型更改为unsigned,这将有助于您增加整数限制