5

配列でFieldOffsetを正しく使用するのに少し問題があります。以下のコードは、私にとって正しく機能しない例です。

[StructLayout(LayoutKind.Explicit)]
public struct IndexStruct {
    [FieldOffset(0)]
    public byte[] data;

    [FieldOffset(0)]
    public short[] idx16;

    [FieldOffset(0)]
    public int[] idx32;
}

たとえば、「data」という名前の配列をシリアル化されたバイト配列に設定し、「idx16」フィールドを使用してデータをshortとして取得しようとすると、インデックスは引き続きbyte[]として整列されます。つまり、idx16 1は、2番目の16ビットワード(バイト2および3)ではなく、データの2番目のバイトをフェッチします。逆の場合、バイトの代わりにショートのインデックスを作成します。これは、オフセットの配置がソースデータから継承されることを意味します。私の質問、これを回避する方法はありますか?要素のサイズを掛けることでインデックス値を補正できることは知っていますが、別の方法はありますか?

これがStackOverflowで見つけた答えですが、そのコードを試してみると、正しく機能していないことがわかりました。VSでユニットテストを使用して、次のコードで試してみましたが、成功しませんでした。

[TestMethod()]
public void SumTest() {
    float[] fArr = {2.0f, 0.5f, 0.0f, 1.0f};
    MemoryStream ms = new MemoryStream();
    for (int i = 0; i < fArr.Length; i++) {
        ms.Write(BitConverter.GetBytes(fArr[i]), 0, sizeof(float));
    }
    byte[] buff = ms.ToArray();
    double expected = 3.5f;
    double actual = Sum(buff);
    Assert.AreEqual(expected, actual);
}

よろしくお願いします!

4

2 に答える 2

8

問題は、(私が見る限り) 配列の参照を統合したことです。そのため、最後に設定された配列が優先されます。配列が作成されると、(バイト オフセットではなく) インデクサーが使用されるため、サイズは問題になりません。

これを「適切に」(または場合によっては不適切に)行う方法は、おそらく安全でないコードを使用することです-配列へのポインターを取得します-次のようなものです:

    IndexStruct s = new IndexStruct();
    s.data = new byte[] { 1, 0, 0, 0, 1, 1 };

    unsafe
    {
        fixed (short* data = s.idx16)
        {
            Console.WriteLine(data[0]); // should be 1 (little-endian)
            Console.WriteLine(data[1]); // should be 0
            Console.WriteLine(data[2]); // should be 257
        }
    }

もちろん、私はそれをお勧めするかどうかはわかりませんが、それはあなたが望むものを達成しているように見えますか?

structまた、を完全に削除して、安全でないアクセスをbyte[]直接使用できるかどうかも疑問です。

    byte[] raw = new byte[] { 1, 0, 0, 0, 1, 1 };
    unsafe
    {
        fixed (byte* addr = raw)
        {
            short* s = (short*)addr;
            Console.WriteLine(s[0]); // should be 1
            Console.WriteLine(s[1]); // should be 0
            Console.WriteLine(s[2]); // should be 257
        }
    }
于 2009-05-08T14:04:16.757 に答える
-2

FieldOffset は、各データ要素が構造体内のどこにあるかを定義します。

それらをすべて 0 に設定することで、すべての位置が 0 であることをコンパイラーに伝えます。

2 番目に表示されるのは、バイト、ショート、および int の配列を作成していることです。

参照: MSDN StructLayoutAttribute

[StructLayout(LayoutKind.Explicit)]
public struct IndexStruct {
        [FieldOffset(0)]
        public byte[16] data;

        [FieldOffset(16)]
        public short idx16;

        [FieldOffset(18)]
        public int idx32;
}
于 2009-05-08T14:11:17.940 に答える