2012-06-18 7 views
7

ポストインクリメント(ORプリインクリメント)は、イコール(=)の右手側でしかできないという印象を受けました。しかし、私は以下のコードをコンパイルすることができます。 この特定のコードを特に以下のように理解してもらえますか? ソース:http://www.ibm.com/developerworks/library/pa-dalign/左側のポストインクリメント

*data8++ = -*data8; 


void Munge8(void *data, uint32_t size) { 
    uint8_t *data8 = (uint8_t*) data; 
    uint8_t *data8End = data8 + size; 

    while(data8 != data8End) { 
     *data8++ = -*data8; 
    } 
} 
+0

割り当て ' - * data8' * data8''へ、その後 'data8'をインクリメント - 効果的data' – Erik

答えて

3

あなたの印象は間違っている、私は推測します。それはstrcpyが実装されているどのくらいの頻度ですが、実際には

*a++ = *b++; 

:あなたは間違いのようなものを行うことができます。あなたも、全く=ずに後または前の増分を持つことができます

a++; 
+0

待ち'で 'size'バイトを否定ので、私は合意していました元の投稿と一緒にどのようにこれは未定義の動作ではないのですか? –

+0

しかし、strcpyはそのように実装されていません。あなたは文字列の最後をより大きなデータ塊のビットパターンで探し、次に大きな塊(通常は64ビット)でデータをコピーします。 –

+0

@sharth:どうしてそれは未定義ですか?私は標準的な中毒者ではないが、RHSは最初に評価され、次にLHSが評価されなければならない。したがって、問題はないはずです。 –

1

ポストインクリメントが代入演算子の左側に行うことができない理由はありません。ポストインクリメント演算子は、以前の状態のオブジェクトの一時コピーを返し、その一時オブジェクト(この場合はポインタ)はそのオブジェクトに対して実行された操作を持つことができます。今

は、の場合:理由はオペレータの順序の

*data8++ = -*data8; 

data8ポインタは、最初の前のポインタ値のコピーを返し、ポストインクリメントされます。その前のポインタ値は逆参照され、代入演算子の右辺の式の結果が代入されます。

編集:他の人が指摘したように、あなたはシーケンスポイントなしでそのメモリ位置への書き込み中に複数回読み込むことでdata8の内容を変更しているので、これは未定義の動作です。

+0

これはどのように定義されていませんか? 'x = -x'が定義されていないと主張するのと同じです。 –

+0

'data8'の内容(つまり、ポインタ値自体)を変更してから、シーケンスポイントのない2つの異なる場所でそれを読み取っています。他の人が指摘しているように、LHSやRHSが最初に評価されれば、2つの異なる結果が得られます。つまり、C-standardは最初に評価されなければならない側面を定義していないからです。 LHSとRHSの評価はインターリーブされる可能性があります!あなたの例では、LHSが 'x'の値を読んでいないので、明確な評価順序があります。それはちょうどそれに書いているだけです。したがって、読み書きは1つしかありません。 – Jason

+0

うん。私は言い訳として睡眠不足を主張します。 –

2

++がポインタに適用され、data8が指す値ではありません。

*data8 = -*data8; 
data8++; 

EDIT:

*data8++ = -*data8;

は同等ですC99 standard 6.5Annex Cを読んだ後
、それは=はシーケンスポイントではありません明らかです。標準には&&,||,,および?しか記載されていません。

data8は全くシーケンスポイントと標準は、RHSが最初に評価されるべきかLHSが最初に評価されるべきかどうかを強制しません=の両側に変更され、以来、私はこれは未定義の動作です確信しています。

Any good reason why assignment operator isn't a sequence point?

これ以上のポストは=はシーケンスポイントでないという議論とはかなりここに関連しています。

+0

'data8'は代入演算子の両側では変更されず、LHSで変更されますが、書込みに対して読取り順序がどのように決定されるかを決定するシーケンスポイントなしで2回読み込まれます。 – Jason

+0

@Jasonあなたは正しいです。 '='シーケンスポイントでないことはここのキーです。 –

7

だから、これは未定義の動作であると確信しています。で最後のセミコロン以外のシーケンスポイントがありません:

*(0x20) = -*(0x20); 

または

*(0x20) = -*(0x24); 

はありませんがあるので:DATA8が0x20のに等しい場合

*data8++ = -*data8; 

は、この等しいです(インターリーブシーケンスポイントなしで変数を2回読み込んで編集したため)未定義の動作です。


次のコードが何をしているのか話すことができます。上記のコードによって意図されている可能性が高いものです。

while(data8 != data8End) { 
    *data8 = -*data8; 
    data8++; 
} 

あなたがここでやっていることはうまくいくほど簡単です。あなたはあなたの入力配列を取って、それを見ているので、それは一連の8ビット数です。次に、インプレースで、それぞれを否定します。

+0

私はあなたがここで "変数"を混同していると思います。ポインタの値とそれによってアドレスポインタに格納される値は、2つの異なるものです。この場合、誰も変数を2回読み込んで編集したことはありません。 "data8"によるアドレスポインタの値は、RHS上で一度読み込まれます。それは一度書き戻されます。ポインターはLHSで1回変更されます。 –

+0

そうかもしれません。 Hehe –

+2

@Vlad、 '= 'はシーケンスポイントではありません。 –

0

私は

* DATA8 ++ =と思います - * DATA8。

DATA8 = *

と等価である - *(DATA8 + 1)。 = DATA8

DATA8 1

関連する問題