C/C++移位运算符出界后的结果是不可预期的

原创 2004年06月21日 13:27:00

以前看到C++标准上说,移位运算符(<<、>>)出界时的行为并不确定:

The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

我当时也没有深究过这个问题。前几天有个网友来信问起这件事,我才发现,这和Intel CPU的移位运算有关。下面是那位网友的来信以及我的回复:


您好!运算符<<作为位操作中的高效的操作,但我遇到一个问题:下面在VC环境下发现一个很不明白的地方,下面标注。

#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。而Intel CPU执行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 masked to 5 bits, which limits the count range to 0 to 31. A special opcode encoding is provided for a count of 1.

C/C++移位运算

一、移位运算符及其规则 移位运算符就是在二进制的基础上对数字进行平移,是在补码的基础上进行操作的。按照平移的方向和填充数字的规则分为三种:>(带符号右移)、>>>(无符号右移)。 左移运算符的规...
  • captain_wangnb
  • captain_wangnb
  • 2016年01月15日 11:17
  • 1786

java移位运算符

移位运算符就是在二进制的基础上对数字进行平移。按照平移的方向和填充数字的规则分为三种:>(带符号右移)和>>>(无符号右移)。   在移位运算时,byte、short和char类型移位后的结果会变成...
  • E01014165
  • E01014165
  • 2016年05月09日 21:24
  • 1203

C++运算符重载(4) - 不能被重载的操作符

C++,中,下面的操作符是不能被重载的: . (成员访问或点操作符) ?: (三元操作符或条件操作符) :: (范围操作符) .* (指向成员的指针操作符) sizeof (取对象大小操作符) typ...
  • shltsh
  • shltsh
  • 2015年05月26日 09:39
  • 2119

运算符重载-编程题#3(C++程序设计第4周)

编程题 #3 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩。) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 写一个二...
  • abc8730866
  • abc8730866
  • 2017年03月03日 21:32
  • 460

C/C++移位运算符

在一般的C语言教学中,移位运算符很多情况下讲师直接跳过,更多的会在汇编语言中系统得讲述。然而,熟练掌握。高级语言中的移位很大程度上可以展现一个人的代码功底并且能提高编程效率。更多内容访问omegaxy...
  • xyisv
  • xyisv
  • 2017年10月24日 11:52
  • 62

C++中不能重载的运算符

C++中不能重载的运算符:“?:”、“.”、“::”和“sizeof”,原因如下: 在具体讲解各个运算符不能重载之前,先来说明下【重载】:重载的本意是让操作符可以有新的语义,而不是更...
  • captain_wangnb
  • captain_wangnb
  • 2016年01月10日 19:37
  • 2767

逻辑运算符、位运算符、移位运算符、三目运算符、运算符的优先级

一、逻辑运算符 :逻辑运算符的作用是用于连接布尔表达式的。 1、& (与,并且) 规律: 只有左右变量同时为true,那么结果才是true,否则就false。2、| (或,或者) 规律: 只要...
  • qq_34944851
  • qq_34944851
  • 2016年09月22日 11:00
  • 2007

java移位运算符详解

java移位运算符不外乎就这三种:>(带符号右移)和>>>(无符号右移)。  1、 左移运算符 左移运算符 1)它的通用格式如下所示: value num 指定要移位值value 移动的位数。 左...
  • sxh850297968
  • sxh850297968
  • 2015年03月13日 17:56
  • 9662

Java移位运算符 “<<” 作用及详解

左移运算符( 基本用法 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 例:a = a 左移1位后a = a *2;  若左移时舍弃的高位不包含1,则每左移一位...
  • zjx409
  • zjx409
  • 2014年07月08日 19:04
  • 2768

【C语言/C++】算术移位和逻辑移位以及一道移位的题目

最近下了个牛客APP,在上面做了几道题。 在做题的过程中呢。我发现了一道比较有意思的题目 老规矩,直接上代码 int main() { int a = 1; int b = 32; printf...
  • qq_31828515
  • qq_31828515
  • 2016年11月22日 15:44
  • 1320
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C/C++移位运算符出界后的结果是不可预期的
举报原因:
原因补充:

(最多只允许输入30个字)