2012-01-13 14 views
2

なぜこのコードが正しいのか理由を説明してください: 私の意見では、p1が先に参照解除されてからインクリメントされるため、++ * p1 = * p2 ++は未定義の動作をしています。これは未定義の動作ですか、なぜですか?

int main() 
{ 
    char a[] = "Hello"; 
    char b[] = "World"; 

    char* p1 = a; 
    char* p2 = b; 

    //*++p1 = *p2++; // is this OK? 
    ++*p1 = *p2++; // is this OK? Or this is UB? 

    std::cout << a << "\n" << b; 

    return 0; 
} 
+6

は、私は誰も今朝は、グループ化についての質問を、なぜだろう、任意の '++'、 '*'と '=' 1恐ろしく複雑で読みにくいライン... – ereOn

+11

であなたがしようとしている場合コードが恐ろしく爆発して黙示録を引き起こすかどうかを判断し、**使用しないでください**。それがどれほど明確に定義されているかにかかわらず、*良いコードではない*。 – ssube

+1

読みやすく透明でない場合は大丈夫です。 – maligree

答えて

9

最初はokです

*++p1 = *p2++ // p1++; *p1 = *p2; p2++; 

第二は、CとUBである++あなたはp1によって2回指さ(一度ので、一度ので、割り当ての増分の)と何のシーケンスはありませんされているもの変更しているので、 2つの副作用を分けるポイント。

C++ 0xルールでは、説明と理解が複雑で複雑になります。 2番目のような意図的な表現を書いたのなら、それはコードゴルフの競争ではないし、私のために働いているなら、あなた自身が解雇されたと考えてください(たとえそれがC++ 0xで合法であっても)。

C++ 0xで合法であるかどうかわかりません。わかりません。私はこのようにそれらを浪費するニューロンが少なすぎます。

+4

+1:「あなた自身が解雇されたと思う」のために、それは私を笑わせました。スマートさは、複雑なコード行を書くのではなく、単純なコードを書くことによって証明されています。 – ereOn

+1

2番目はC++ 03とC++ 11の両方でUBではありません。 –

+0

@SergeDundich:C++標準では、「前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトの格納された値は、しばしば式の評価によって変更されます。 2番目のケースは、シーケンスポイントのない単一の式で、同じスカラー値に2回書き込んでいます。 – 6502

1

どちらも未定義の動作です。さらに、の実装は、またはと定義されていません。です。

これらの2つの行は両方とも明確に定義されていますが、異なるものです。

*++p1 = *p2++; 

_T1* _p1 = ++p1; 
T2_* p2_ = p2++; 
*_p1 = *p2_; 

そして

++*p1 = *p2++; 

と同等です

T1& x = *p1; 
__T1_& y = ++x; 
T2_* p2_ = p2++; 
y = *p2_; 

どこ

に相当します
  • T1&

    はすなわち、すべてのT1/_T1/__T1_/T2_があり、

  • __T1_&++(*p1)式の型があり、

  • _T1*++p1式の型、
  • T2_*p2++式の型があるがあり、*p1式のタイプでありますあなたの場合はcharです。あなたのケースでは(C++のネイティブ型用)++x以来

xへの戻り参照はxyには同一の参照(すなわち*p1)です - しかし、オーバーロードでT1は、いくつかのカスタムタイプになる場合、それはケースではないかもしれませんoperator++()

ADD:

が明らかに値をインクリメントし、それに割り当てることは全く無意味です。

はい、他の人のように、すでにこのような質問があるコードは書かれていません。読者にはっきりしていることを明確に書いてください。

ADD2:

係争のポイントを明確にするために、私は標準を引用します。

ISO/IEC 14882から2003 5.3.2:

  1. 接頭語のオペランド++ 1を加えることによって修飾されている、またはそれが ブール値である場合(この使用は推奨されている)をtrueに設定します。オペランドは、変更可能な 左辺値でなければならない。オペランドの型は、完全に定義されたオブジェクト型へのポインタである算術型または でなければならない。値はオペランドの新しい の値です。それは左辺値です。 xがbool型でない場合、 式++ xはx + = 1と等価です。
+0

2番目の式では、lvalue '* p1'がシーケンスポイントのない単一の式で2回(インクリメントと代入)変更されています。これはC++のUBです。この場合、なぜあなたはそれが合法だと思いますか? – 6502

+0

@ 6502: "2番目の式では、lvalue' * p1'が2回変更されました。 "No. Lvalue' * p1'は 'operator ++ 'によって1回変更されます。その後、lvalue '++(* p)'( 'operator ++ 'の戻り値)は代入演算子によって変更されます。 –

+0

@ 6502:評価の2つの式の間にシーケンスポイントがない場合でも(例えば 'f(++ x、++ x)'のように)、その式の評価の順番は**未指定です**ので**未定義の動作**ではありません。 –

関連する問題