user-0 提问: 太奇怪了，为啥两个结果不同

回复:
user: user-0
content: 我在VS2010上写是这样的，版主可以试试

user: user-1
content: 。。。25？  很难想象

user: user-2
content: 引用 29 楼 zxj10620 的回复:[quote=引用 28 楼 lin5161678 的回复:] [quote=引用 27 楼 lm_whales 的回复:] 虽然是未定义行为，但是 debug 和 Release 结果不同，也应该是Bug 未定义行为就可以出现 同一个编译器 结果不同结果的现象  不是编译器的BUG 好嘛  [/quote] 再请教一下，我还不是太明白，那个j值为什么会是未定义行为呢？[/quote] 因为在Debug下一般没有优化，所有的步骤都是一步步来的。对于变量i，它在做右移的时候可能会先判断是否大于32，如果大于32则取该数膜，然后再进行右移。 但是对于Release下，编译器会进行优化，它会去掉它认为毫无意义的步骤，在编译期前就会直接把i替换成34。所以j=100%i，实际上就是100%34，所以结果会变成0。  当然，对于常量右移时是否进行取膜，也要看编译器实现。不过一般能在编译期间确定的事，编译器就不会拿到运行期进行操作。而编译期间一般是不会分步骤去执行，所以取膜过程也没有进行。所以100%34只会是0，而100%i，则要看是否进行了优化，这样就有两个结果，这就是一个典型的不确定行为。

user: user-3
content: 常量折叠，不能算优化 const int a =10;  int *p=&a;  *p=100;  printf("a =%d,*p=%d",a,*p); //有些编译器，输出 10，100；不知是不是所有编译器，都这么处理。  a = 10 ，是所谓的常量折叠。这只是编译器，保证常量正确的手段，不能算优化。  常量代换，才是优化  int shift(int x,int y){     return x >> y;      // x 替换成常量100，y 替换成常量34， 计算结果为0      //结果是这里生成 xor eax,eax          //相当于mov eax, 0   }  int main(){ int x=100,i=34; cout<<(x>>i)<<endl; }

user: user-3
content: 引用 28 楼 lin5161678 的回复:[quote=引用 27 楼 lm_whales 的回复:] 虽然是未定义行为，但是 debug 和 Release 结果不同，也应该是Bug 未定义行为就可以出现 同一个编译器 结果不同结果的现象  不是编译器的BUG 好嘛  [/quote] 好吧！

user: user-4
content: 编译器看到 i 只在 100>>i 这个地方用了，就直接将 i 优化成34了。

user: user-4
content: 楼上有人说debug和release版结果不同，那是因为release版做优化了，debug版会尽量不优化。

user: user-4
content: 首先说第二个，100>>34，两边都是立即数，编译器直接优化了，所以结果是0. 第一个：int i = 34; 100>>i 此时 i 是变量，编译器无法优化，只能在运行时依照标准来，将i的值与上一个掩码：cpu位数 - 1，即：32位上是 i & 31 ，取 i 的低 5 位。也就是说当 i 的值是 34 时，在32位机器上实际上 100>>i 变成了 100>>2.

user: user-0
content: 引用 28 楼 lin5161678 的回复:[quote=引用 27 楼 lm_whales 的回复:] 虽然是未定义行为，但是 debug 和 Release 结果不同，也应该是Bug 未定义行为就可以出现 同一个编译器 结果不同结果的现象  不是编译器的BUG 好嘛  [/quote] 再请教一下，我还不是太明白，那个j值为什么会是未定义行为呢？

user: user-5
content: 引用 27 楼 lm_whales 的回复:虽然是未定义行为，但是 debug 和 Release 结果不同，也应该是Bug 未定义行为就可以出现 同一个编译器 结果不同结果的现象  不是编译器的BUG 好嘛

user: user-3
content: 引用 19 楼 lin5161678 的回复:[quote=引用 17 楼 lm_whales 的回复:] #include <iostream> using namespace std; int shiftConst(int x){ 	return x>>34; }  int shiftVar(int x,int i){ 	return x>>i; }  int main() { 	int i=34; 	int x=100; 	cout<<(100>>34)<<endl; 	cout<<(100>>i)<<endl;  	cout<<shiftConst(x)<<endl; 	cout<<shiftVar(x,i)<<endl; 	cin.get(); 	return 0; } release : 0       //直接用常量计算，这个结果是编译器，自己算出来的。  0       //常量代换，结果相当于，直接用常量计算，这个结果是编译器，自己算出来的。 0       //常量代换，结果相当于，直接用常量计算，这个结果是编译器，自己算出来的。 0       //常量代换，结果相当于，直接用常量计算，这个结果是编译器，自己算出来的。  debug: 0         //直接用常量计算，这个结果是编译器，自己算出来的。 25        //有变量，应用程序计算出来的。   25        //有变量，应用程序计算出来的。  25        //有变量，应用程序计算出来的。  PS：  这应该是VC10 的Bug ,原因应该是， VC编译器的开发者，使用的编译器，没有按照 新编译器的方式处理这种计算，结果就是，用常量计算，按照开发新VC编译器的那个编译器（版本）的方法计算。 用变量计算，编译器生成，按照新编译器的方法，计算的代码。  结果常量表达式的计算结果，以及常量代换优化后的代码的结果，还是0；  使用变量计算的，不使用常量代换优化的代码，结果是25； 未定义行为被你说成是bug  编译器何其无辜  另外 编译期求值 / 运行期求值 直观一点 不是什么 编译器算 应用程序算[/quote]  虽然是未定义行为，但是 debug 和 Release 结果不同，也应该是Bug 编译期求值 / 运行期求值 只是术语而已，  编译期求值，不就是编译器把结果求出来，直接给出答案，编译生成的应用程序中，省略计算步骤吗？ 运行期求值，不就是编译器直接，生成计算代码，让应用程序自己去计算吗？  关键是英文术语原文，我不清楚。  现在同一个术语，有不同的翻译，真个是百花齐放； 在没有对照原文的时候，不清楚哪个更准确一点，有可能都翻译得不好。  所以，这种自己不能确定，是否翻译准确的术语，自然不用为好。 还是大白话来得实在。都能看懂。

user: user-6
content: 一个是常量折叠，在编译时直接算的，一个是在运行时算的，由于34>32，属于未定义行为，所以两个结果都正常

user: user-7
content: 同意是优化产生的差异，可以反汇编看看编译器做了什么。

user: user-8
content: 一个是按照>>2来算的； 为0的结果应该是大于32，编译器直接优化掉了，可以关优化试试。

user: user-9
content: 引用 6 楼 user-13 的回复:[quote=引用 5 楼 netbooting 的回复:] [quote=引用 3 楼 zxj10620 的回复:] 刚才在ubuntu下面也试了，也是一样的结果  又自己查了一下 结果如下链接： http://blog.csdn.net/wmda999/article/details/17032331  你给的链接都已经给出原因了。 当要移动的位大于实际位数时，实际移动的位是和编译器相关的。  100是int占32位，现在要移动34位，实际上只移动了34%32=2位，100>>2=25[/quote]  那么请问为嘛100>>34就变0了呢?[/quote]  100>>34是在编译阶段算出的为0，在输出时直接push 0，而100>>i是在运行时通过移位操作来完成的。

user: user-10
content: 前一个，位移值只有最后5位起作用。 后一个，应该是被编译期优化掉了

user: user-11
content: 不要深究大于位数的位移行为。  引用 楼主 zxj10620 的回复:int i = 34; int j = 100>>i; j的值为25  而 int i = 34; int j = 100>>34; j的值为0   求各位大大帮忙解答啊，困惑得不行

user: user-12
content: 100右移7位的时候已经是0值了，如果右移很大的话编译时编译器已经告诉你：计数为负或过大，其行为未定义。所以不要纠结这个了，没有意义

user: user-13
content: 引用 5 楼 netbooting 的回复:[quote=引用 3 楼 zxj10620 的回复:] 刚才在ubuntu下面也试了，也是一样的结果  又自己查了一下 结果如下链接： http://blog.csdn.net/wmda999/article/details/17032331  你给的链接都已经给出原因了。 当要移动的位大于实际位数时，实际移动的位是和编译器相关的。  100是int占32位，现在要移动34位，实际上只移动了34%32=2位，100>>2=25[/quote]  那么请问为嘛100>>34就变0了呢?

user: user-9
content: 引用 3 楼 zxj10620 的回复:刚才在ubuntu下面也试了，也是一样的结果  又自己查了一下 结果如下链接： http://blog.csdn.net/wmda999/article/details/17032331  你给的链接都已经给出原因了。 当要移动的位大于实际位数时，实际移动的位是和编译器相关的。  100是int占32位，现在要移动34位，实际上只移动了34%32=2位，100>>2=25