1

学習のために、私は最近、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;

理由がわかりません。コンパイラがこのように動作する理由を知りたいです。

  1. このようなキャストを生成するのはなぜですか (また、ユーザーが作成したコードでこれを行うことが受け入れられないのはなぜですか)?
  2. 最初の例の void* の += 演算子はどうなっていますか? buffer += (void*)wrtn where buffer is void* ???? を生成した元のコード コードは何ですか?
4

2 に答える 2

1

2 番目の点については、void* にはサイズ情報がないため、コンパイラはポインターをどれだけインクリメントするかを知りません。sizeof(double) ずつインクリメントする必要がありますか? 型情報だけが何を期待するかを知っています。

編集:実際、これは最初のポイントにも当てはまります。コンパイラは、増分するデータ型のサイズを知る必要があります。Void* にはサイズ情報が存在しないため、byte* にキャストすることで、ポインターを sizeof(byte) * wrtn だけインクリメントする必要があることをコンパイラーに知らせます。

Edit2:あなたの明確化により、リフレクターが適切にキャストされた型(バイト*)ではなく、void*としてコードを発行する理由を尋ねているようです。これは、パラメーターの型から型情報が抽出され、メソッドで単純に使用されていることが原因である可能性が最も高いです。これはおそらく、コンパイラよりも Reflector の問題です。

また、このポインター コードが IL 内の型情報を失う可能性もあります。まだテストしていませんが、リフレクターが適切に出力するために型情報 (データのサイズ以外) を IL に転送しない可能性があります (通常の ' safe' IL には常にこの型情報が必要です)。この場合、Reflector はデフォルトで void* または最も近い推論された型になります。

于 2009-11-02T18:17:57.650 に答える
0

学習の目的で、最近、既存のアセンブリを調べました (Reflector を使用)

ここでの唯一の問題は、Reflector の使用です。明らかに、IL から元の C# コードを推測するのはあまり得意ではありません。IL 自体は正しく、キャストはありません (何も必要ありません。IL では、ポインターと整数引数をスタックにプッシュし、加算/減算を行います)。リフレクターがおかしい。

于 2009-11-02T18:35:35.217 に答える