Vraag Kunnen we de wijzer in een vak gebruiken?


Zo nee, waarom niet? Gebruik van unie over structuur ??


11
2018-01-20 14:35


oorsprong


antwoorden:


U kunt elk gegevenstype gebruiken in een unie, er is geen beperking.

Wat het gebruik van vakbonden boven structuren betreft, leggen structuren hun gegevens sequentieel in het geheugen op. Dit betekent dat al hun subcomponenten gescheiden zijn.

Vakbonden daarentegen gebruiken hetzelfde geheugen voor al hun subcomponenten, zodat er maar één tegelijkertijd kan bestaan.

Bijvoorbeeld:

                                 +-----+-----+
struct { int a; float b }  gives |  a  |  b  |
                                 +-----+-----+
                                    ^     ^
                                    |     |
                 memory location:  150   154
                                    |
                                    V
                                 +-----+
union { int a; float b }  gives  |  a  |
                                 |  b  |
                                 +-----+

Structuren worden gebruikt wanneer een "object" is samengesteld uit andere objecten, zoals een puntobject bestaande uit twee gehele getallen, namelijk de x- en y-coördinaten:

typedef struct {
    int x;           // x and y are separate
    int y;
} tPoint;

Vakbonden worden meestal gebruikt in situaties waarin een object een van de vele dingen kan zijn, maar slechts één tegelijk, zoals een opslagsysteem zonder type:

typedef enum { STR, INT } tType;
typedef struct {
    tType typ;          // typ is separate.
    union {
        int ival;       // ival and sval occupy same memory.
        char *sval;
    }
} tVal;

Ze zijn handig voor het besparen van geheugen, hoewel dat tegenwoordig steeds minder een zorg is (anders dan bij werk op een laag niveau zoals ingesloten systemen), zodat u er niet veel van ziet.


11
2018-01-20 14:52



Goed, volgens ISO / IEC 9899: TC3 (de C99-norm):

Een vakbondtype beschrijft een overlappende niet-lege verzameling lidobjecten, elk van   die een optioneel gespecificeerde naam en mogelijk een ander type heeft.

Kortom, de geheugenruimte van vakbondsleden overlapt, en de namen die je aan vakbondsleden geeft, laten je geheugen op die locatie in grootte lezen. Overwegen:

#include <stdio.h>
#include <stdint.h>

typedef union
{
    struct
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    };
    uint32_t x;
} somenewtype;

typedef union
{
    uint32_t* p;
    uint8_t* q;
} somepointer;

int main(int argc, char** argv)
{
    uint32_t r;
    uint8_t s;
    somenewtype z;
    somepointer p;
    r = 0x11223344; s = 0x11;
    z.x = 0x11223344;
    p.p = &r;
    p.q = &s;
    printf("%x%x%x%x\n", z.d, z.c, z.b, z.a);
    printf("%x %x\n", *(p.p), *(p.q));
}

In de eerste printf is het printen van 8-bits delen van het 32-bits gehele getal. Hopend natuurlijk op geen opvulling in die anonieme structuur.

In de tweede printf? Ik moest gdb gebruiken om te begrijpen, maar ik deed het:

p.p = (uint32_t *) 0x7fffffffde5c;
p.q =  (uint8_t *) 0x7fffffffde5b "\021D3\"\021P\337\377\377\377\177";
p.p = (uint32_t *) 0x7fffffffde5b;

Natuurlijk zijn aanwijzers allemaal even groot, dus toewijzen p.q overschrijft het adres van p.p. Ik vermoed sterk dat het refereren van het adres van het 32-bits gehele getal naar een 8-bit pointer "alles wat zich op die locatie bevindt + 32 bits in grootte" afdrukt, wat overigens voor mij toevallig zo is 22334411. Maar ik vermoed dat het gedrag op dat moment ongedefinieerd is.

Hoe dan ook, het punt van die kleine oefening was om je te laten zien dat:

  • vakbonden kunnen worden gebruikt om toegang te krijgen tot dezelfde geheugenlocatie via een andere "type" modifier.
  • Je moet voorzichtig zijn met wat je doet en het onderliggende type dat je gebruikt begrijpen. Als u pointers gaat gebruiken, pas dan op met hun wijziging, want u kunt beginnen te wijzen op wie weet wat.

Ik moet erop wijzen dat ik het praktische gebruik ervan kan zien somenewtype maar niet voor somepointer - Dat was een geforceerd voorbeeld waarvan ik zeker wist dat het zou breken.


4
2018-01-20 15:17