c#

位置:IT落伍者 >> c# >> 浏览文章

复杂表达式的执行步骤 - .Net编程


发布日期:2022年02月19日
 
复杂表达式的执行步骤 - .Net编程

近日在CSDN上闲逛的时候注意到一个帖子

((*strDest =*strSrc )!=\) 哪儿前辈可以解释下里面具体执行的步骤呢?

对于这样的表达式我们通常会有这样三种看法

这种写法不但没有错误(当然也没有BUG)而且写法紧凑

这种写法虽然没有错误但是不够直观理解起来有点麻烦可能还会导致理解错误

这种写法中存在未定义的地方执行结果可能是错误的

粗略来看这三种说法都有点道理我顿时有了刨根问底的兴趣想对这个问题进行一次深入的分析对于这种组合表达式在分析的时候我们应该抓住两个关键的概念优先级(Precedence)和关联性(Associativity)

优先级(Precedence)优先级决定了那些表达式的值先被评估那些表达式的值后被评估通常情况下优先级高的表达式的值先被评估出来后然后用评估的结果再去评估那些优先级低的表达式所以如果我们将优先级搞反了评估出来的结果是错误的

(Associativity)对于二目表达式关联性决定了左边的表达式还是右边的表达式先被评估先被评估出来的结果再用来评估另外的表达式

再抓住这两个关键的同时我们还应该分清什么是表达式的值什么是变量的值我们在评估表达式的时候我们感兴趣的是表达式的值而不是构成表达式的某些变量的值在很多情况下表达式的值和某些变量的值是一致的所以我们很容易混淆表达式的值和变量的值要知道在有些情况下表达式的值并不和某些变量的值相同

有了上面的理论来武装我们对表达式的分析就显得游刃有余了

很明显上面的表达式是一个组合表达式组合表达式由子表达式组成子表达式又可能是组合表达式这样就形成了一个树状的数据结构对表达式的评估就类似于对树结点的遍历首先我们应该注意到()操作符它具有最高的优先级所以从整体来看整个表达式应该是个!=操作!=左边又是一个组合表达式而右边是一个常量\很明显下面的工作就是评估(*strDest =*strSrc )

在这一步我们要对表达式(*strDest =*strSrc )进行评估由于赋值表达式具有较低的优先级所以表达式 又可以写成(*strDest ) = (*strSrc )所以整个表达式是个=操作=左边又是一个组合表达式右边也是一个组合表达式这里就需要从关联性来判断左边还是右边也被评估由于=的关联性是从右到左所以(*strSrc )先被评估(*strDest )后被评估

在这一步我们要对表达式(*strSrc )进行评估由于 的优先级大于*所以表达式又可以写成*(strSrc )我们要先对表达式strSrc 进行评估然后用表达式的值再去评估*(strSrc )的值对于表达式strSrc 这里要需要注意区分变量的值和表达式的值对于后增表达式表达式的值是变量strSrc的值然后变量strSrc的值会也就是说表达式的值是strSrc变化前的值而strSrc的值会发生变化值得注意的是我们知道strSrc的值会发生变化但是我们却不知道strSrc的值发生变化的具体时间这个变化具体的执行时间由编译器决定了这就决定了任何依赖strSrc的表达式的值是不确定的具体的值依赖编译器的实现完成了对strSrc 的评估后取值操作符就对表达式的值所对应的内存空间进行取值操作

在这一步我们要对表达式(*strDest )进行评估具体的评估的分析完全和中的分析一致

在这一步我们要对表达式(*strDest ) = (*strSrc )进行评估这是个赋值表达式将右表达式的值赋给左边表达式的值值得注意的是对于赋值表达式表达式本身的值等于左边子表达式的值

由于!=表达式左边的子表达式的值已经被评估出来了下面就执行!=操作!=表达式的是一个布尔值

通过以上深入的分析我们知道这个表达式完成了以下多个功能

对于指针strDest strSrc将strSrc所指的内存空间的值赋给由strDest所指的内存空间

判断赋值后的strDest所指的内存空间的指是否等于

对于指针strDeststrSrc他们的值分别加即指向下一个元素

我们可以看出一个表达式完成了三个功能表达式写的确实相当紧凑而且这个表达式的值是可以确定的因为所有的分析都是建立在C 标准的基础上对于能否在实践的代码中使用这样的代码这就智者见智了关键一点就是要遵循项目的代码规范

上一篇:C#高级编程:事务处理和命令

下一篇:剖析.NET Framework框架[1]