2009年03月11日
川俣晶の縁側ソフトウェア技術雑記total 8581 count

C#において、x++;はx += 1;に置き換えられるが、x = x + 1;に置き換えられるとは限らない

Written By: 川俣 晶連絡先

 ushortを多用したC#ソースをいじっているうちに気付きました。

 C#で記述された以下のソースコード断片があるとします。

ushort x = 0;

x++;

 ここの2行目を以下のように置き換えることができ、同じ結果が得られます。

x += 1;

 しかし、以下のように書き換えるとコンパイルエラーになり、

x = x + 1;

 エラー内容は以下の通りです。

  • エラー 1 型 'int' を 'ushort' に暗黙的に変換できません。明示的な変換が存在します。(cast が不足していないかどうかを確認してください)

 intよりも小さいビットサイズの型を使うと、たぶんどれでも同じような現象が起きるだろうと思います。intならx = x + 1;への置き換えも上手く行きます。

WHY? §

 あらためて調べてみると興味深いことに、x++;とx += 1;とx = x + 1;の挙動の根拠は全て違います。

 まず、x = x + 1;についてはC#には16bit/8bitの加算が存在しない問題で述べたように、ushortの加算が存在しないため"x + 1"の型はintになり、intからushortへの暗黙変換が存在しないためにエラーになります。

 次に、x += 1;ですが、これは複合代入に対する以下のルールによって記述可能になっています。つまり暗黙的にキャストが補われています。

• 選択された演算子が定義済みの演算子で、選択された演算子の戻り値の型を x の型に "明示的に" 変換でき、y を x の型に "暗黙に" 変換できる場合または演算子がシフト演算子の場合、演算は x = (T)(x op y) として評価されます。ただし、T は x の型で、x は 1 回だけ評価されます。

 最後にx++;ですが、これは以下のように"+"よりも多くの型に対する演算子が用意されているために、記述可能となっています。

sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal の各型およびすべての列挙型には、定義済みの ++ 演算子と -- 演算子があります。

 ちなみに、生成したバイナリを逆アセンブルして見たところ、どれも同じでした。定義済のushort型++演算子があっても、ILレベルに落ちるときにはやはり32bit加算を経由する、ということなのでしょう。たぶん。

感想 §

 ここ数年、毎日のようにC#のコードを書いていましたが、こういう基本的な部分にこのような問題があったとは。かなり新鮮です。

Facebook

キーワード【 川俣晶の縁側ソフトウェア技術雑記
【技術雑記】の次のコンテンツ
2009年
03月
14日
C言語のconstとenumのまとめ
3days 0 count
total 7515 count
【技術雑記】の前のコンテンツ
2009年
03月
05日
C#には16bit/8bitの加算が存在しない問題
3days 0 count
total 8865 count

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

https://mag.autumn.org/tb.aspx/20090311175535
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.36 (Alpha-Test) Copyright (c) 2004-2021 Pie Dey.Co.,Ltd.