0

C++ プロジェクトをフォークし、いくつかのケースをスイッチに追加しました。そして、次のケースの途中でジャンプします。条件は anintで、ケースの値は#defined です。コードが大きいので、同等で単純なものをここに書きます。

#define AAA 1
#define BBB 2
int X::func(int i) {
  bool b = (i == 5);
  int v = (b ? 10 : 5);
  switch (i) {
    case AAA:
      if (b && v > 4) {
        v = v + 1;
        return 0;
      }
      break;
    case BBB:
      if (!b || v > 40) {
        v = v + 2;
        b = false; // direct jump here from the switch for i = AAA
        return 0;
      }
      break;
  }
return -1;
}

AAA を X::func に渡すと、コードの実行は BBB ケース内のswitchtoから直接ジャンプします。b = false;実際のコードでは、数十のケースがあり、途中で発生します。まるっとコメントcase BBBすると、コメントの同じところにジャンプ!すべてのケースは a で終わり、break;内部に変数宣言はありません。ここで変数 b と v のように、それらは switch ステートメントの前に宣言されます。

ケースの一部は#ifdef #endifブロックになっています。問題が発生する追加のケースは、このブロックにあります。条件が true であるため、ブロックがコンパイルされます。いずれにせよ、これら 2 つのプリコンパイラ ステートメントを抑制した後でテストしましたが、結果は同じでした。

ここのように括弧を追加{}してケースを完全に囲むと、同じ結果が得られます。

case BBB: {
  if (!b || v > 40) {
    v = v + 2;
    b = false; // direct jump here from the switch for i = AAA
    return 0;
  }
  break;
}

デバッグセッションでも通常の実行でも、すべてが正常にコンパイルされ、同じように実行されます。Eclipse CDT Indigo で gcc 4.5.4 を使用しています。

コンパイラのバグのように見えますが、何が原因でしょうか?

4

2 に答える 2

0

デバッガーを介して関数をステップ実行している場合、デバッガーの「現在強調表示されている行」は、現在実行されている行に必ずしも対応していません (ループが含まれている場合、最適化がオンになっている場合、多数のマクロがある場合など)。

スイッチの後に変数を stdout/stderr に出力し、それらの値が正しいかどうかを確認します。また、いくつかのデバッグ行を両方の stdout/stderr に出力しますcases。得られた出力が正しければ、奇妙なコードの実行順序について心配する必要はありません。

例:

#define AAA 1
#define BBB 2
int X::func(int i) {
  bool b = (i == 5);
  int v = (b ? 10 : 5);
  std::cout << "before switch/case" << std::endl;
  switch (i) {
    case AAA:
      std::cout << "AAA, before if block" << std::endl;
      if (b && v > 4) {
        v = v + 1;
        std::cout << "within AAA if block" << std::endl;
        return 0;
      }
      std::cout << "AAA, after if block" << std::endl;
      break;
    case BBB:
      std::cout << "BBB, before if block" << std::endl;
      if (!b || v > 40) {
        v = v + 2;
        b = false; // direct jump here from the switch for i = AAA
        std::cout << "BBB, within if block" << std::endl;
        return 0;
      }
      std::cout << "BBB, after if block" << std::endl;
      break;
  }
  std::cout << "after switch/case" << std::endl;
  return -1;
}

- 編集 -

case ステートメントに {} ブラケットを追加すると役立つ場合があります。

case AAA:{
    break;
}

また、ケースから別の機能に移動すると、間違いなく役立ちます。これでコードが改善されることはありませんが、デバッガーは間違いなくそれらをウォークスルーできます。

于 2013-09-13T13:33:42.977 に答える