Question

J'ai quelques difficultés à utiliser correctement FieldOffset avec des tableaux. Le code ci-dessous est un exemple où cela ne fonctionne pas correctement pour moi:

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

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

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

Si I, par exemple, définit le tableau nommé "données". dans un tableau d’octets sérialisé, puis essayez d’extraire les données en abrégé à l’aide de la commande "idx16". field l'indexation est toujours alignée comme un octet []. Ce qui signifie que idx16 1 récupère le deuxième octet dans les données, pas le deuxième mot de 16 bits (octets 2 et 3). Si je fais l'inverse I, je mets un short au lieu d'octets, ce qui signifie que l'alignement du décalage est hérité des données source. Ma question, y at-il un moyen de contourner cela? Je sais que je peux compenser la valeur d'index en multipliant par la taille de l'élément, mais existe-t-il un autre moyen?

ici est une réponse que j'ai trouvée ici sur StackOverflow, mais en essayant ce code, il s'est avéré qu'il ne fonctionnait pas correctement. Essayé en utilisant un test unitaire dans VS avec le code suivant sans aucun succès:

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

Merci d'avance!

Était-ce utile?

La solution

Le problème est (d'après ce que je peux voir) que vous avez unifié les références des tableaux - afin que le dernier tableau défini soit le dernier. Une fois qu'il y a un tableau, il utilise l'indexeur (pas le décalage d'octet) - la taille importe donc peu.

Le moyen de le faire "correctement" (ou incorrectement, selon le cas) serait probablement avec un code non sécurisé - en prenant le pointeur sur le tableau - quelque chose comme:

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

Bien sûr, je ne suis pas sûr de le recommander - mais cela semble donner ce que vous voulez?

Je me demande également si vous pouvez supprimer complètement la struct et simplement utiliser un accès non sécurisé à un octet [] directement:

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

Autres conseils

Votre FieldOffset définit l'emplacement de chacun de vos éléments de données dans la structure.

En les définissant tous sur 0, vous indiquez au compilateur qu’ils se trouvent tous à la position 0.

La deuxième chose que je vois, c'est que vous créez un tableau d'octets, de shorts et d'ints.

voir: MSDN StructLayoutAttribute

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

        [FieldOffset(16)]
        public short idx16;

        [FieldOffset(18)]
        public int idx32;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top