Non ho capito le unioni

di il
9 risposte

Non ho capito le unioni

Salve a tutti
sto studiano il c sul libro di deitel "corso comleto di programmazione C", sono arrivato al capitolo sulle strutture e le unioni, le prime le ho capite abbastanza bene, le seconde meno
qualche anima buona me le può spiegare/passare una guida che le spiega

9 Risposte

  • Re: Non ho capito le unioni

    Anche se i forum non dovrebbero essere un sostituto dei libri rispondo ugualmente.
    Come dice la parola unisce,se hai piu tipi di variabili le puoi unire in una sola.
    
        union variant
        {
            int i;
            char c;
        };
    
    variant contiene due nomi "v" e "b" ma in realtà nella memoria conterrà solo la variabile di dimensione maggiore,in questo caso l'int.Dato che abbiamo in memoria lo spazio per una sola variabile allora vuol dire che l'unione variant potrà contenere O un int O un char, ma a differenza delle strutture che le contiene entrambi l'unione conterrà solo ed esclusivamente un tipo.
    Quindi variant potrà essere o un int usandola come "variant.i" o un char usandola come "variant.c",cambiando ".i" cambierò ".b" e cambiando ".b" cambierò ".i" .
    L'unione viene spesso usata quando una variabile può assumere diversi tipi.
    
    int main()
    {
    
        enum VTYPE{vchar,vint,vdouble};
    
        struct TRUEVARIANT
        {
            enum VTYPE tipo;
            union
            {
                int i;
                char c;
                double d;
            }val;
        };
    
        struct TRUEVARIANT v;
    
        //int type
        v.tipo = vint;
        v.val.i = 1980;
        
        /*
        //char type
        v.tipo = vchar;
        v.val.c = 'f';
        */
        
        /*
        //char type
        v.tipo = vdouble;
        v.val.d = 18.5;
        */
        
        printf("var:");
    
        switch (v.tipo)
        {
            case vchar:
                printf("%c\n",v.val.c);
            break;
            case vint:
                printf("%d\n",v.val.i);
            break;
            case vdouble:
                printf("%f\n",v.val.d);
            break;
        }
    
        return 0;
    }
    
    mi son spiegato?
  • Re: Non ho capito le unioni

    Esatto.
    Quindi il primo problema e': come si fa a sapere che cosa c'e' in un certo momento in un oggettto di tipo "variant"?
    Guardando solo l'union, non si puo'!

    Questa conoscenza deve essere da qualche altra parte: o nella logica del programma stesso (in un certo momento usi l'intero e sai che lo stai usando), o in un flag messo da qualche parte.

    Nell'esempio precedente, nel campo 'tipo' .

    Altro esempio che ho implementato proprio questa mattina:

    ho la seguente struttura dati (non ho usato questa, ma una piu' complessa, ma il concetto e' lo stesso):
    
    struct S
    {
       long n;
       long *p;
    };
    
    dove 'n' e' il numero di elementi del vettore puntato da 'p'
    Fintanto che 'n'>1 va tutto bene e non si puo' fare altrimenti.

    Ma se 'n' e' 1, avrei un gran spreco di memoria (immagina di avere 10^9 istanze di S ) perche' dovrei allocare lo spazio per S PIU' lo spazio per un vettore di UN elemento.

    se invece uso:
    
    struct S
    {
       long n
       union {
          long v;
          long *p
       }
    }
    
    ecco che posso risparmiare bel il 30% di memoria allocata.

    Dirai, ma con 16GB o 32GB di ram che te ne frega di risparmiare il 30% di memoria!
    Ebbene l'applicazione su cui sto lavorando richiede un sacco di memoria, e piu' riesco a risparmiare, piu' grande e' il problema che posso risolvere
  • Re: Non ho capito le unioni

    Emmmm.....
    36% per la precisione.
    In questo caso però non ne vale assolutissimamente la pena,anzi,complichi notevolmente la gestione del programma inutilmente,compreso il suo tempo di esecuzione che per cosi tanti elementi potrebbe diventare critico.
    Le unioni le ho viste usare per tantissime cose, ma "praticamente" mai per risparmiare memoria, dato che per definizione una unione implementa il tipo di dimensione maggiore allora rimane ben poca memoria da risparmiare.
    In casis estremi puoi usare un qualsiasi puntatore come se fosse una variabile int:
    
    int main()
    {
        struct S
        {
            long n;
            long* v;
        }mys;
    
        mys.n = 1;
        mys.v =(long*) 10;
    
        if (mys.n == 1)
        {
            printf("%ld\n",(long)mys.v);
        }
        else
        {
            //...normale gestione vettore
        }
    
        return 0;
    }
    
    ma queste sono semplicemente cose brutte brutte brutte.
  • Re: Non ho capito le unioni

    Come ho scritto, quello descritto e' un esempio per spiegare all'autore come funziona una union, non ho spiegato perche' nel caso reale e' stata fatta un'implementazione basata su questa idea.

    Da un punti di vista della manutenzione (cosa mai da trascurare), la tua soluzione, cioe' quella di usare un puntatore come un intero, e' estremamente inelegante. Non scorretta, si puo' fare, ma decisamente da evitare.

    La union sta' li apposta per evitare l'accrocchio puntatore->intero.

    Dal punto di vista del tempo di esecuzione, invece, le soluzioni sono equivalenti, perche' tutto viene risolto dal compilatore.

    Eseguire
    s->p = (long*)10
    oppure
    s->v = 10
    viene implementato esattamente nello stesso modo. E quindi eseguito nello stesso tempo.

    Invece, se vogliamo guardare il pelo nell'uovo, e' sicuramente piu' efficiente eseguire
    p->v = 10
    che che eseguire
    p->p[0] = 10
    cosa che dovrei fare nel caso in cui n sia 1.
    C'e' anche il banale problema di quanti byte servono per allocare nello heap un long (8 byte).
    Che non sono, ovviamente 8 byte !

    E il 30% (o 36% per la precisione ) di risparmio indicato e' pure una sottostima!
  • Re: Non ho capito le unioni

    Come ho scritto, quello descritto e' un esempio per spiegare all'autore come funziona una union, non ho spiegato perche' nel caso reale e' stata fatta un'implementazione basata su questa idea.
    Lo so,ma hai postato uno dei piu bruttini(a mio parere ovvio).
    Da un punti di vista della manutenzione (cosa mai da trascurare), la tua soluzione, cioe' quella di usare un puntatore come un intero, e' estremamente inelegante. Non scorretta, si puo' fare, ma decisamente da evitare.
    Infatti l'ho scritto,che è un'implementazione brutta brutta.
    il punto a mio avviso poco "elegante" è il dover continuamente controllare in ogni utilizzo della struttura se c'è un elemento oppure molteplici elementi,questo complica notevolmente la gestione della struttura per un piccolo risparmio di memoria che magari potrebbe essere migliorato a mote.
    Ci sono passato anche io e ho sempre prediletto il codice alla memoria.
    Per il tempo di esecuzione non mi riferivo all'uso di un puntatore al posto dell'unione,ma alla tecnica di gestione della struttura,teoricamente se devo fare piu controlli per gestire della struttura sempre teoricamente sarà piu lenta la sua esecuzione.In pratica però è vero che può avvenire il contrario.

    il 36% è il calcolo teorico,anche la struct molto probabilmente non sarà semplicemente la somma dei vari tipi di variabili.
    ma lavori su un 64 bit?(8 byte per long) e ti preoccupi della memoria?
  • Re: Non ho capito le unioni

    Si quando passo dal 40% al 25% della memoria allocata, solo cambiando il modo in cui le strutture dati vengono allocate.

    Ricorda, che avere puntatori a 64 bit, non vuol dire avere 2^64 byte di memoria .
    E purtroppo non tutte le piattaforme hardware supportano la memoria virtuale, o i memory mapped files.
  • Re: Non ho capito le unioni

    vbextreme ha scritto:


    anche se i forum non dovrebbero essere un sostituto dei libri rispondo ugualmente
    scusa se in un forum di programmatori pensavo di trovare qualcuno in grado di aiutare qualcun' altro se ne avesse bisogno, poi ho chiestodopo non avere capito quello che diceva il libro, scusa se penso che qui ci potrebbero essere persone migliori di un libro, eviedentemente mi sbagliavo.Mi dispiace di averti fatto sprecare del tempo
    @migliorabile grazie per la risposta
  • Re: Non ho capito le unioni

    montefr ha scritto:


    scusa se in un forum di programmatori pensavo di trovare qualcuno in grado di aiutare
    Lascia stare ... non e' il caso di essere polemici
  • Re: Non ho capito le unioni

    Hai trovato piu di uno ad aiutarti!ed non è colpa mia ma dei forum.IL LINGUAGGIO SI STUDIA SUI LIBRI e per il resto c'è il forum.è una regola dei forum non una mia filosofia di vita!altrimenti non ti avrei proprio risposto!
    Si quando passo dal 40% al 25% della memoria allocata, solo cambiando il modo in cui le strutture dati vengono allocate.
    e poi finisci a far chissà quale pasticcio......
    Non dico che l'implementazione per il tuo caso sia efficente,dico solo che per una risposta ad un thread per chi non ha capito le union sia troppo complesso.
    Ricorda, che avere puntatori a 64 bit, non vuol dire avere 2^64 byte di memoria :( .
    E purtroppo non tutte le piattaforme hardware supportano la memoria virtuale, o i memory mapped files.
    è vero se si somma stack ed heap(forse) è molto di piu,scusa...
    Non ho mai lavorato con i 64bit ma con i 32-16 e 8 si,e il problema della memoria non l'ho mai risentito,se non in qualche sporadico caso.
    Dubito molto che con solo 10^9 elementi tu ti sia posto il problema della memoria...
    Ho lavorao ad un "pseudo" progetto per implementare tutti i nomi delle persone nel mondo circa 7.000.000.000,la memoria usata era circa meno del kb....il tutto naturalmente su microprocessore da 8bit...Non parlo di dati salvati ma di memoria del software.
    Quando si lavora con molti dati è un errore metterli tutti in memoria,perchè nella realtà massimo ne serviranno un migliaio,volendo propio esagerare!!!
Devi accedere o registrarti per scrivere nel forum
9 risposte