Frage

Ich bin ein bisschen ein Problem mit Verwendung FieldOffset korrekt mit Arrays. Der folgende Code ist ein Beispiel, wo es nicht richtig für mich funktioniert:

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

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

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

Wenn ich zum Beispiel das Array legt den Namen „data“ auf eine serialisierte Byte-Array und dann versuchen, Daten wie Shorts abzurufen unter Verwendung des „idx16“ Feld, um die Indizierung noch als byte [] ausgerichtet ist. Was bedeutet, dass idx16 1 holt das zweite Byte in Daten, nicht das zweite 16-Bit-Wort (Byte 2 und 3). Wenn ich die inverse I-Index Shorts anstelle von Bytes, was bedeutet, dass die Offset-Ausrichtung aus den Quelldaten vererbt wird. Meine Frage, gibt es eine Möglichkeit, dies zu umgehen? Ich weiß, dass ich den Indexwert durch Multiplikation mit der Größe des Elements zu kompensieren, aber gibt es einen anderen Weg?

Hier ist eine Antwort, die ich hier auf Stackoverflow gefunden, aber wenn dieser Code versucht, es stellte sich heraus, dass es nicht richtig funktionierte. mit einem Unit-Test in VS mit dem folgenden Code ausprobiert ohne Erfolg:

[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);
}

Vielen Dank im Voraus!

War es hilfreich?

Lösung

Das Problem ist (von dem, was ich sehen kann), dass Sie die haben unioned Referenzen der Arrays - so Unabhängig davon, welche Array wird gesetzt gewinnt letzte. Einmal gibt es ein Array ist, ist es den Indexer (nicht Byte-Offset.) - so die Größe keine Rolle spielt

Die Art und Weise, dies zu tun „richtig“ (oder falsch, wie es der Fall sein kann), wahrscheinlich mit unsicherem Code wäre - der Zeiger auf das Array nehmen - so etwas wie:

    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
        }
    }

Natürlich, ich bin nicht sicher, ob ich es empfehlen - aber das scheint zu erreichen, was Sie wollen

?

Ich frage mich auch, ob Sie vollständig die struct fallen können und nur unsicheren Zugang zu einem byte[] direkt verwenden:

    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
        }
    }

Andere Tipps

Ihr FieldOffset definiert, wo jedes Ihrer Datenelemente innerhalb der Struktur ist ..

Durch sie alle auf 0 setzen, doch sagen Sie den Compiler, dass sie alle auf Position 0.

Das zweite, was ich sehe, ist ein Array von Bytes, Shorts erstellen, und ints.

siehe: MSDN StructLayoutAttribute

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

        [FieldOffset(16)]
        public short idx16;

        [FieldOffset(18)]
        public int idx32;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top