Hvordan kan jeg simulere en C ++ union i C #?

stemmer
9

Jeg har et lite spørsmål om strukturer med LayoutKind.Explicitattributtet sett. Jeg erklærte structsom du kan se, med en fieldTotalmed 64 bits, er fieldFirstde første 32 bytes og fieldSecondde siste 32 bytes. Etter å ha satt både fieldfirstog fieldSecondtil Int32.MaxValue, jeg forventer fieldTotalå være Int64.MaxValue, som faktisk ikke skjer. Hvorfor er det sånn? Jeg vet C # ikke virkelig støtter C ++ fagforeninger, kanskje det vil bare lese verdiene godt når interoping, men når vi prøver å sette verdiene oss det rett og slett ikke vil håndtere det veldig bra?

[StructLayout(LayoutKind.Explicit)]
struct STRUCT {
    [FieldOffset(0)]
    public Int64 fieldTotal;

    [FieldOffset(0)]
    public Int32 fieldFirst;

    [FieldOffset(32)]
    public Int32 fieldSecond;
}

        STRUCT str = new STRUCT();
        str.fieldFirst = Int32.MaxValue;
        str.fieldSecond = Int32.MaxValue;
        Console.WriteLine(str.fieldTotal); // <----- I'd expect both these values
        Console.WriteLine(Int64.MaxValue); // <----- to be the same.
        Console.ReadKey();
Publisert på 21/07/2009 klokken 23:19
kilden bruker
På andre språk...                            


3 svar

stemmer
10

Årsaken er at FieldOffsetAttribute tar et antall bytes som parameter - ikke antallet bits. Dette fungerer som forventet:

[StructLayout(LayoutKind.Explicit)]
struct STRUCT
{
    [FieldOffset(0)]
    public Int64 fieldTotal;

    [FieldOffset(0)]
    public Int32 fieldFirst;

    [FieldOffset(4)]
    public Int32 fieldSecond;
}
Svarte 21/07/2009 kl. 23:27
kilden bruker

stemmer
6

Ser på hex verdier hvis Int32.MaxValue og Int64.MaxValue bør gi svaret.

Nøkkelen er den mest signifikante bit. For et positivt heltall, blir den mest signifikante bit bare satt for et negativt tall. Så max verdi av Int32 er en 0, etterfulgt av en hel serie av 1s. Rekkefølgen er likegyldig, bare at det vil være minst en enkelt 0-bit. Det samme gjelder for Int64.MaxValue.

Nå vurdere hvordan en union skal fungere. Det vil i hovedsak legge ut biter av verdiene ved siden av hverandre. Så nå har du et sett med bits 64 i lengde som inneholder to 0 biters verdier. En for hver av de Int32.MaxValue tilfeller. Dette kan aldri være lik Int64.MaxValue siden det kan inneholde bare en enkelt 0 bit.

Merkelig nok vil du sannsynligvis få atferden du leter etter hvis du setter fieldSecond å Int32.MinValue.

EDIT Tapte at du trenger å gjøre det FieldOffset (4) i tillegg.

Svarte 21/07/2009 kl. 23:25
kilden bruker

stemmer
4

Ben M ble en av de viktigste elementene - din definisjon ikke er satt opp riktig.

Når det er sagt, vil ikke dette fungere - selv i C ++ med en fagforening. Verdiene du spesifiserte ikke vil være (og bør ikke være) de samme verdiene, siden du bruker signert (ikke usignerte) ints. Med en signert int (Int32), du kommer til å ha en 0 litt etterfulgt av 1 bits. Når du gjør unionen, vil du ende opp med en 0 litt med, etterfulgt av en haug med 1 bit, så en annen 0 bit, så en haug med 1 bits ... Den andre 0 bit er det som får deg opp.

Hvis du brukte uint32 / uint64, vil dette fungere eiendom, siden den ekstra tegn bit ikke eksisterer.

Svarte 21/07/2009 kl. 23:28
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more