ポインター演算と C# コンパイラー
-
12-09-2019 - |
質問
学習の目的で、私は最近、Win32 WriteFile を使用する既存のアセンブリ (Reflector を使用) を調べました。実装は次のとおりです。
Write(IntPtr handleFile, void* bufferData, uint length){
void* buffer = bufferData
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
// This does not compile, because of the cast but also simply because void* does not have += operators (it is unknown size).
buffer += (void*)wrtn;
len -= wrtn;
}
}
実は最後の2行が問題なのです...1 つは、コンパイラが uint を void* にキャストできないというエラーを表示することです。さらに、void* はサイズが不明であるため、+= または + を使用することはできません。
Write(IntPtr handleFile, void* bufferData, uint length){
byte* buffer = (byte*)bufferData
while (length > 0)
{
uint wrtn;
if (!WriteFile(handle, (void*)buffer, len, out wrtn, IntPtr.Zero))
{
// Do some error handling
}
// This works! I can add to a byte*
buffer = buffer + wrtn; // I could also have used buffer += wrtn
len -= wrtn;
}
}
上記のコードは機能しますが、最後の数行は次のようにコンパイルされます。
buffer += (byte*)wrtn;
理由がわかりませんが、コンパイラがこのように動作する理由を知りたいと思っています。
- なぜこのようにキャストを生成するのでしょうか (また、ユーザーが作成したコードでこれを行うことが受け入れられないのはなぜですか)?
- 最初の例の void* の += 演算子はどうなっているのでしょうか?どのような元のコードが生成したバッファ += (void*)wrtn ここでバッファも void* ????
解決
さて、あなたの第二の点について、コンパイラにより、ポインタをインクリメントするどのくらい知っていないので、void *型にはサイズ情報を持っていません。それははsizeof(ダブル)によってインクリメントすべきか?唯一の型情報とそれが期待するのか分からない。
編集:実は、これは同様にあなたの最初のポイントに適用されます。コンパイラは、データ型の増分の大きさを知る必要があります。ボイド*あなたはコンパイラがwrtn *はsizeof(バイト)でポインタをインクリメントする必要があることを知っている* byteにキャストすることにより、その存在なしサイズ情報を持っていません。
EDIT2:あなたの明確化と、リフレクターが、それが適切にキャストの型(バイト*)としてvoid *型としてコードを放出する代わりに、なぜあなたが求めている表示されます。最も可能性が高いこれは、パラメータの型から抽出されたタイプ情報に起因すると幾分単純方法で使用されています。これはおそらく、コンパイラよりも多くの反射の問題です。
反射器が適切に放出するためのILにはまた、このポインタコードは、それが、私はまだそれをテストしていないILの情報を入力します失うことは可能だが、それは、(データのサイズ以外に)入力情報を搬送しないかもしれ(通常の「安全な」ILは、常にこのタイプの情報を持っている必要があります)。このケースだった場合リフレクターは、*または最寄りの推論されたタイプが無効にするために、デフォルトがあります。
他のヒント
私は最近、既存のアセンブリを見て学習の目的のために(使用リフレクター)
ここでの唯一の問題は、反射板を使用している - どうやら、それはILから元のC#のコードを推測ではあまり良くありません。 IL自体は正しいです、そして何のキャスト(なしは必要ありません - ILに、あなたは、スタック上のポインタと整数の引数をプッシュし、加算/減算を行う)しています。リフレクターが間違ってます。