首页 > 试题广场 >

以下代码输出什么?

[单选题]
以下代码输出什么?
int a = 1, b = 32;
printf("%d,%d", a << b, 1 << 32);
  • 1,1
  • 1,0
  • 0,0
  • 取决于编译器
执行a<<b时,编译器会先将b与31进行and操作,以限制左移的次数小于等于31。b&31=0,则a<<b=1
执行1<<32时,编译器直接执行算术左移的操作。
 来自 http://blog.csdn.net/hgl868/article/details/7058909

发表于 2015-11-08 21:10:29 回复(2)
这道题目有问题,首先上VS2015,以及GCC4.84的代码以及结果




其次 这个表达式本身就是不合法的。它会出现什么结果也是未定义的。
看《C陷阱与缺陷》 7.5移位运算符,p110: n<<32 或 n<<-1是非法的

最后,既然是未定义,所以取决于编译器!
发表于 2016-02-02 21:43:55 回复(12)
#include <stdio.h>
void main()
{
   unsigned int i,j;
   i=35;
 
   //为什么下面两个左移操作结果不一样?
   j=1<<i;  // j为8
   j=1<<35; // j为0
}

原因是这样的:i=35;j=1<<i;这两句在VC没有做优化的情况下,将被编译成下面的机器指令:

mov dword ptr [i],23h
mov eax,1
mov ecx,dword ptr [i]
shl eax,cl
mov dword ptr [j],eax

在shl一句中,eax=1,cl=35。而IntelCPU执行shl指令时,会先将cl与31进行and操作,以限制左移的次数小于等于31。因为35 & 31 =3,所以这样的指令相当于将1左移3位,结果是8。

而j=1<<35;一句是常数运算,VC即使不做优化,编译器也会直接计算1<<35的结果。VC编译器发现35大于31时,就会直接将结果设置为0。这行代码编译产生的机器指令是:

mov dword ptr [j],0

对上面这两种情况,如果把VC编译器的优化开关打开(比如编译成Release版本),编译器都会直接将结果设置为0。

所以,在C/C++语言中,移位操作不要超过界限,否则,结果是不可预期的。

下面是Intel文档中关于shl指令限制移位次数的说明:

The destination operand can be a register or a memory location.The count operand can be an immediate value or register CL. The count is maskedto 5 bits, which limits the count range to 0 to 31. A special opcode encodingis provided for a count of 1.

根据:http://blog.csdn.net/hgl868/article/details/7058909
发表于 2017-01-22 12:05:28 回复(4)
这道题我没有作对,于是就亲身实践了一下,做了一下实验,貌似有这样的规律,当两个操作数都是常量时(也不准确,因为const时,也会如前者),当移动位数超过了限界,结果将会为0.即1<<32 = 0;1<<33 = 0;1<<34=0;。。。。。
当两个操作数中有一个为变量时,将会变成算术左移
int a =1;
int b = 32;
a<<b = 1;a<<33 = 2;1<<b = 1;

const int a = 1;
a<<b = 1;
发表于 2015-11-08 18:38:24 回复(2)
总结: 如果有变量 , 不管在 << 的左还是右 , 都会循环左移 , 超过左边 , 就从右边出来
            如果两边都是数字 , 如 1 << 32  , 就会进行算数左移 , 也就是如果超过 , 那就直接消失
发表于 2017-06-11 12:07:23 回复(0)
a<<b ==> a<<a&b;
1<<32 ==> 1<<32;
发表于 2016-04-02 16:03:56 回复(0)
执行a<<b时,编译器会先将b与31进行and操作,以限制左移的次数小于等于31。b&31=0,则a<<b=1
执行1<<32时,编译器直接执行算术左移的操作。
发表于 2016-09-09 12:18:47 回复(0)
我的理解是这样的,int 是4个字节,4*8=32个位,1<<32个位相当于2^32,int存储不下溢出会直接归0
发表于 2022-09-23 09:15:50 回复(0)
这道题我没有作对,于是就亲身实践了一下,做了一下实验,貌似有这样的规律,当两个操作数都是常量时(也不准确,因为const时,也会如前者),当移动位数超过了限界,结果将会为0.即1<<32 = 0;1<<33 = 0;1<<34=0;。。。。。
当两个操作数中有一个为变量时,将会变成循环左移。
int a =1;
int b = 32;
a<<b = 1;a<<33 = 2;1<<b = 1;

发表于 2020-04-04 20:58:41 回复(0)
a<<b 是循环移位
发表于 2016-07-11 16:27:18 回复(1)

右移位数不允许大于32,否则是未定义行为,左移位数无限制。在VS中,若是两个立即数之间的右移大于等于32则为0,如1<<33。若任何一个为变量,则超过32之后最开始进行循环位移,如int a=1; int b = 33; a<<33 or 1<<b or a<<b。也就是说右移33位相当于右移1位。或者说超过32的右移次数会被转换成n%32的右移次数。

编辑于 2021-11-14 14:35:43 回复(0)
移位首先观察是否越界,即31位,移位越界则结果无法预测;否则移位数是变量先与31作&操作,常量则可以直接&运算
发表于 2017-08-19 11:20:52 回复(0)
c++ primer 5th, 英文版 第153页 ,有句&ldquo;the right-hand operand must not be nagative and must be a value that is strictly less than the number of bits in the result, otherwise,the operation is undefined.&rdquo;
发表于 2017-07-21 17:22:59 回复(0)
发表于 2017-06-09 15:56:52 回复(0)
 在VS2010中编写了如下代码:
编译的时候出现警告warning C4293: “<<”: Shift 计数为负或过大,其行为未定义

但是运行也能出现结果
发表于 2017-05-24 10:16:12 回复(0)
在vs2013中   输出的结果是1,1

发表于 2017-03-29 14:12:41 回复(0)
vs2015社区版实测,会显示警告……
发表于 2017-01-16 10:03:08 回复(0)
未定义,看编译器
发表于 2016-10-07 20:18:02 回复(0)
C
发表于 2016-08-28 11:36:30 回复(0)