0
点赞
收藏
分享

微信扫一扫

未定义行为


先看第一个小程序

int main(void)
{
int i = 0;
int a[] = {10, 20, 30};
int b = 1*a[i++] + 2*a[i++] + 3*a[i++];

printf(“b = %d\n”, b);
return 0;
}

 

请思考:上述程序输出b = ?

 

思考完毕,再看第二个小程序

int main(void)
{
int a = 5, b = 0;
b = ++a * ++a;

printf(“b = %d\n”, b);
return 0;
}

请问,这里的b = ?

……

       用gcc 4.6.1编译后运行,我们发现第一个程序中输出的结果是:b = 60,而不是我们想的通过操作符的优先级得到的140。 同样,第二个程序输出的结果也是出乎意料的:b = 49。为什么会这样呢? o_O!!其实这是未定义行为。


(undefined)行为,即C++标准没有定义的行为。


        造成上述问题是由于对后缀自加或后缀自减的误解,因为没有保证自增或自减会在输出变量原值之后和对表达式的其它部分进行计算之前立即进行,也不能保证变量的更新会在表达式完成。

“多个不确定副作用”是指在同一个表达式中使用导致同一对象修改两次或修改以后又被引用的自增,自减和赋值操作符的任何组合。


经典教程《C++Primer》中有相关说明:

        使用了未定义行为的程序都是错误的,即使程序能够运行,也只是巧合。未定义行为源于编译器不能检测到的程序错误或太麻烦以至无法检测的错误。

        不幸的是,含有未定义行为的程序在有些环境或编译器中可以正确执行,但并不能保证同一程序在不同编译器中甚至在当前编译器的后继版本中会继续正确运行,也不能保证程序在一组输入上可以正确运行且在另一组输入上也能正确运行。

        程序不应该依赖未定义行为。

int的位数是个固定且已知的值。我们称这样的程序是不可移植的。当程序移植到另外一台机器上时,要寻找并更改任何依赖机器相关操作的代码。在本来可以运行的程序中寻找这类问题是一项非常不愉快的任务。

 

bug。其实正常情况下,我们不会这样用,也不知道能否这样用,而这种“无知”恰恰也保护了我们。

举报

相关推荐

0 条评论