加载中…
个人资料
Winters
Winters
  • 博客等级:
  • 博客积分:0
  • 博客访问:72,709
  • 关注人气:6
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

关于表达式求值顺序的问题C++&&C#的区别

(2010-03-12 16:53:18)
标签:

杂谈

分类: 计算机与 Internet
 
    最近看到C#里将表达式的求值顺序,突然想到以前也有同事问到过C/C++的求值顺序,于是就找资料
又彻底的看了一番,又是深有感悟。(误人啊误人啊,好多资深程序员,教员估计也没搞清楚呢)

    先说说C#吧,C#语言明确规定了:运行时,表达式一定是严格按照从左到右的顺序计算的。
    虽然计算结果组合方式会受到优先级(precedence),结合性(associativity)的影响,但操作数在运行时
的求值顺序不受影响。比如说 x + y * z 里,x率先被求值,然后是y,最后是z。
    注意的是: 不能因为 乘法 发生在 加法之前就认为 y和z在 x之前求值的。
    所以,比如如下代码:
    namespace Test02_ConsoleApplication1
   {
        class Program
        {
            static int f(int a)
            {
                Console.WriteLine("f : a={0}", a);
                return a;
            }
            static int g(int a)
            {
                Console.WriteLine("g : a={0}", a);
                return a;
            }
            static int h(int a)
            {
                Console.WriteLine("h : a={0}", a);
                return a;
            }

            static void Main(string[] args)
            {
                int a = 10;
                int y = f(a) + g(a++) * h(a);   // 10 + 10 * 11 = 120
                Console.WriteLine("y = {0}, a ={1}", y, a);
            }
        }//End Class
    }//End namespace
 
   运行结果:
   : a=10
   g : a=10
   h : a=11
   y = 120, a =11
   根据C#的求值顺序,先计算f的,然后是g,最后是h,然后根据运算符的优先级,结果就是 10 + 10 * 11 = 120了。
   换句话说,在对y求值的算式中,a的值已经时11了。

    我们在看看C/C++语言,
    比如说一个简单的: m = 1; n = m+++m++;
    我们说说,n=多少呢 ?要回答这个问题,就要仔细看一下C/C++语言的特性了。(不要盲目地回答)
    裘宗燕教授特别地写了篇文章<C/C++语言中表达式的求值>来说明这个问题。
    C/C++语言中没有明确规定表达式的运算顺序(从左到右,或是从右到左),这点与C#及Java语言都不同。C/C++中,
除了逻辑&&, ||, 及条件运算符是首先计算第一个表达式的值之外,其他所有的二元运算符都没有明确规定,先计算左
边的还是右边的,具体的实现由具体的系统来设计决定。系统会出于效率性,优化性等各方面的要求,来决定在运行时
运算顺序左 --〉右,或是 右--〉左。
   程序语言通常都规定了执行中变量修改的最晚实现时刻,也叫顺序点(Sequence Point)。程序执行中存在一系列的顺
序点,语言保证一旦执行到达一个顺序点了,那么在此之前发生的所有修改(副作用Side Effect, 自增/减)都必须实现(必
须反映到随后对同一存储位置的访问上),在此之后的所有修改都还没有发生。在顺序点之间则没有任何保证。C/C++
许可表达式中有副作用的语言。
-----------------------------------
 C/C++顺序点的概念:
1. 每个完整表达式结束时。(return, switch, for, 条件,循环)
2. 运算符 &&, ||, ?: 和逗号运算符的第一个运算对象计算之后。
3. 函数调用中对所有实际参数和函数名表达式的求值完成之后(进入函数体之前)。
-----------------------------------
   所以,对于上面的例子 “m = 1; n = m+++m++;” ,C/C++下n的结果 ?
   正确回答是:不知道。原因: C/C++语言没有明确规定,到底如何顺序计算表达式的值。
   所以,很多书籍里如果说先算左边,或是右边,都是错误的!!!
   (上面同样的C#的例子,用C/C++来写,Debug / Release模式的结果都不一样, VS2005, SP1版)

 PS:尤其是面试题中如果这么考你,如果选择项里没有 "不知道" 这个选项,那这家公司不用考虑了。
        填空题另当别论了。

裘宗燕教授的这篇文章<C/C++语言中表达式的求值>
http://www.is.pku.edu.cn/~qzy/technotes/expression2009.pdf

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有