3

flex と bison を使用して単純なコンパイラを実装しようとしていますが、後置表記で行き詰まりました。(コンパイラは C++ コンパイラのように動作する必要があります)

問題は次のとおりです。次のコードを考えます。

    int x = 0;
    int y = x++ || x++  ; //y=1 , x = 2 this is understandable

    int z = x++ + x++ ;  // z = 0 , x=2

次の文法により、最初の行は問題ありません。

    expression = expression || expression; //  x=0
    expression = 0 || expression   // x= 1
    expression = 0 || 1  //x=2
    expression = 1 // x=2 
    y = 1

ただし、なぜz=0なのかわかりません。

私のバイソン文法が「変数」++を見ると、最初に変数値を返し、それから1だけインクリメントします.C++の仕組みだと思っていましたが、「z」変数では機能しません。

このケースを解決する方法について何かアドバイスはありますか?

4

2 に答える 2

2
int z = x++ + x++;

z は 0 に見えるかもしれませんが、そうではありません。実際には任意の値である可能性があり、使用しているコンパイラに完全に依存します。これは、z の代入が未定義の動作をするためです。

未定義の動作は、シーケンス ポイント間で x の値が複数回変更された場合に発生します。C++ では、|| 演算子はシーケンス ポイントであるため、y の割り当てが期待どおりに機能しますが、+ 演算子はシーケンス ポイントではありません。

もちろん、C++ には他にもさまざまなシーケンス ポイントがあります。もっと顕著な例です。

また、++ 演算子が変数の前の値を返すことも指摘しておく必要があります。これは、この例にあります。

#include <iostream>

using namespace std;

int main() {
    int x = 0;
    int y = x++;
    cout << y << endl;
    return 0;
}

y に対して出力される値は 0 です。

于 2012-12-01T12:57:48.497 に答える
0

同じことを別の言い方で。AC コンパイラは自由に実装できます

int z = x++ + x++;

どちらかとして

 z = x + x
 incr x
 incr x

またはとして

 int r1 = x;
 incr x
 z = r1 + x
 incr x

コンパイラは最初のプランを使用しているようです。

于 2012-12-02T20:15:50.437 に答える