RISOLTO [C] Strutture, Unioni ed Enumerazioni

Stato
Discussione chiusa ad ulteriori risposte.

demda

Utente Attivo
Ciao a tutti, sto studiando le strutture, le unioni e le enumerazioni. Non mi sono chiare alcune cose:

1) A quanto ho capito la differenza tra strutture ed unioni (dato che la sintassi è praticamente la stessa) sta nel fatto che nelle seconde se voglio preservare il contenuto di una delle variabili non posso utilizzare tutte le altre poiché sono memorizzate tutte nella stessa area di memoria (quindi la scrittura su una variabile comporterà una perdità di dati sulle altre), cosa che non accade per le strutture dove le variabili sono mantenute in aree di memoria diverse (quindi sono indipendenti).
Non ho capito cosa significa che in un' unione tutte le variabili condividono la stessa area di memoria ?

2) Cosa sono le enumerazioni ? e quale potrebbe essere il loro utilizzo ? (di questo argomento non ci ho capito quasi niente :suicidio:)

Grazie a tutti
 

Andretti60

Utente Èlite
3,721
2,501
Hardware Utente
Il concetto di Union e' tipico del genere "godereccio" del linguaggio C, dove tutto e' possibile. Diciamo pure che e' utile sapere della loro esistenza, ma le Union vengono comode solo agli hacker piu' incalliti.

Structure e Union sono due concetti completamente diversi, l'unica cosa in comune e' la loro sintassi. Ma a differenza della Structure, dove ogni membro ha il suo posto in memoria, TUTTI i membri della Union usano la stessa memoria, che e' quindi la piu' grande tra quelle dei membri.

Vengono usate per diversi motivi, ma non molti. Per esempio, si vuole ottimizzare lo spazio di memoria allocato, e si sa gia' che quei valori NON saranno mai usati allo stesso tempo. Oppure si vuole accedere alla stessa posizione di memoria SENZA fare un casting. Utile per esempio per convertire un numero a virgola mobile nella sua rappresentazione binaria. Ma piu' comunemente viene usata per retro-compatibilita'. Per esempio, supponiamo che si ha scritto un file binario dove un valore fu scritto in decimale. Con il tempo lo si vuole cambiare in virgola mobile. Il trucco e' di leggere il valore in una Union con un decimale e un double, e poi accedere al suo valore a seconda della versione.
Post automaticamente unito:

La ENUM funzione in pratica come la definizioni di costanti (numeriche). Si puo' assegnare valori alle dichiarazioni, oppure lasciare che il compilatore le assegni automaticamente (in valore incrementale).

E' utile quando NON si vuole usare delle costanti numeriche all'interno del proprio codice. Per esempio, l'istruzione
if (posizione == 34) e' ambigua, nel senso che chi la legge non ha idea cosa rappresenti il numero 34
Invece l'espressione if (posizione == SonoAlCesso) , dove SonoAlCesso e' definita all'interno di una enum, fa subito capire dove io sia in quel momento.

In altre parole, le ENUM rendono il codice piu' leggibile e compatto (proprio come i #define per esempio)
 
Ultima modifica:
  • Mi piace
Reactions: fabio93 e demda

demda

Utente Attivo
Il concetto di Union e' tipico del genere "godereccio" del linguaggio C, dove tutto e' possibile. Diciamo pure che e' utile sapere della loro esistenza, ma le Union vengono comode solo agli hacker piu' incalliti.

Structure e Union sono due concetti completamente diversi, l'unica cosa in comune e' la loro sintassi. Ma a differenza della Structure, dove ogni membro ha il suo posto in memoria, TUTTI i membri della Union usano la stessa memoria, che e' quindi la piu' grande tra quelle dei membri.

Vengono usate per diversi motivi, ma non molti. Per esempio, si vuole ottimizzare lo spazio di memoria allocato, e si sa gia' che quei valori NON saranno mai usati allo stesso tempo. Oppure si vuole accedere alla stessa posizione di memoria SENZA fare un casting. Utile per esempio per convertire un numero a virgola mobile nella sua rappresentazione binaria. Ma piu' comunemente viene usata per retro-compatibilita'. Per esempio, supponiamo che si ha scritto un file binario dove un valore fu scritto in decimale. Con il tempo lo si vuole cambiare in virgola mobile. Il trucco e' di leggere il valore in una Union con un decimale e un double, e poi accedere al suo valore a seconda della versione.
Post automaticamente unito:

La ENUM funzione in pratica come la definizioni di costanti (numeriche). Si puo' assegnare valori alle dichiarazioni, oppure lasciare che il compilatore le assegni automaticamente (in valore incrementale).

E' utile quando NON si vuole usare delle costanti numeriche all'interno del proprio codice. Per esempio, l'istruzione
if (posizione == 34) e' ambigua, nel senso che chi la legge non ha idea cosa rappresenti il numero 34
Invece l'espressione if (posizione == SonoAlCesso) , dove SonoAlCesso e' definita all'interno di una enum, fa subito capire dove io sia in quel momento.

In altre parole, le ENUM rendono il codice piu' leggibile e compatto (proprio come i #define per esempio)
Circa il discorso delle unioni e strutture sei stato molto chiaro, mi hai tolto quasi ogni dubbio. Il "pallino" che mi è rimasto in testa è il seguente:

È legittimo manipolare i puntatori per accedere ai membri di una variabile di tipo struttura, ho fatto delle prove con il seguente codice, e non ho riscontrato problemi di compilazione ne esecuzione (quindi SUPPONGO di si) . Ma la mia domanda resta sempre la stessa: È legittimo ?

C:
#include <stdio.h>

typedef struct prova{
    int a;
    char b;
}nuovoTipo;

int main (int argc, char *argv[]){
    nuovoTipo a = {25, 'A'};
    void *p = &a;
    char *ptr = p+4;
    int *ptr1 = p;
    
    printf("%c\n",*ptr);
    printf("%d\n",*ptr1);
    
    return 0;
}
Post automaticamente unito:

Un'altra domanda che mi sono dimenticato di porti riguarda i campi di bit: Se scrivo una cosa del genere:

C:
#include <stdio.h>

typedef struct var_booleane{

    unsigned int val: 1;
    
}Boolean;

int main (int argc, char *argv[]){
    Boolean prova1;
    
    printf("%d\n",sizeof(Boolean));
    
    /*    Output: 4   */
    
    printf("%d\n",sizeof(int));
    
    /*    Output: 4   */
    
    return 0;
}
se non ho capito male la variabile val della struttura utilizzerà 1 solo bit di spazio in memoria, però:

1) eseguendo il codice (come scritto anche sotto forma di commenti) l'output della sizeof( Boolean ) è 4 Byte, quindi la dimensione di un intero, suppongo quindi che in realtà la variabile Boolean prova1 occupi 4 Byte ma ne siano accessibili soltanto 1 bit. È corretto questo ragionamento, o mi sto perdendo ??

2) In caso il ragionamento appena fatto fosse corretto, quale potrebbe essere una reale utilità dell'utilizzare questi campi di bit ? o sono solo una sorta di "presa per i fondelli" ? (dubito)
Post automaticamente unito:

Il concetto di Union e' tipico del genere "godereccio" del linguaggio C, dove tutto e' possibile. Diciamo pure che e' utile sapere della loro esistenza, ma le Union vengono comode solo agli hacker piu' incalliti.

Structure e Union sono due concetti completamente diversi, l'unica cosa in comune e' la loro sintassi. Ma a differenza della Structure, dove ogni membro ha il suo posto in memoria, TUTTI i membri della Union usano la stessa memoria, che e' quindi la piu' grande tra quelle dei membri.

Vengono usate per diversi motivi, ma non molti. Per esempio, si vuole ottimizzare lo spazio di memoria allocato, e si sa gia' che quei valori NON saranno mai usati allo stesso tempo. Oppure si vuole accedere alla stessa posizione di memoria SENZA fare un casting. Utile per esempio per convertire un numero a virgola mobile nella sua rappresentazione binaria. Ma piu' comunemente viene usata per retro-compatibilita'. Per esempio, supponiamo che si ha scritto un file binario dove un valore fu scritto in decimale. Con il tempo lo si vuole cambiare in virgola mobile. Il trucco e' di leggere il valore in una Union con un decimale e un double, e poi accedere al suo valore a seconda della versione.
Post automaticamente unito:

La ENUM funzione in pratica come la definizioni di costanti (numeriche). Si puo' assegnare valori alle dichiarazioni, oppure lasciare che il compilatore le assegni automaticamente (in valore incrementale).

E' utile quando NON si vuole usare delle costanti numeriche all'interno del proprio codice. Per esempio, l'istruzione
if (posizione == 34) e' ambigua, nel senso che chi la legge non ha idea cosa rappresenti il numero 34
Invece l'espressione if (posizione == SonoAlCesso) , dove SonoAlCesso e' definita all'interno di una enum, fa subito capire dove io sia in quel momento.

In altre parole, le ENUM rendono il codice piu' leggibile e compatto (proprio come i #define per esempio)
Per quanto riguarda le enumerazioni,finalmente ho capito cosa sono e come poterle utilizzare. Una cosa mi preme, il discorso memoria. Ovvero le costanti definite quando dichiaro un enumerazione quanto spazio occupano in memoria ? di che tipo sono (int, short, long, float ...) ?
 
Ultima modifica:

Andretti60

Utente Èlite
3,721
2,501
Hardware Utente
Ah, qui entriamo in un campo difficile: memory packing. Il compilatore C assegna ad ogni campo della struttura un numero di byte in modo da renderne più facile l’accesso, aggiungendo byte qua e là. Per esempio anche se dichiari un dato char o specifichi un numero preciso di bit, il compilatore effettuerà un “padding” aggiungendo byte in modo che l'offset del campo successivo sia un numero pari o, più comunemente, un multiplo di 4 (ossia 32 bit). Ma non esiste uno standard, ogni compilatore implementa il proprio padding. Per accedere a un campo della struttura usando un puntatore puoi usare l'operatore Offsetof.

Per quanto riguarda lo spazio degli ENUM, non esiste uno standard, più probabilmente viene usato il int in quanto è l'intero di default. Ricorda comunque che la descrizione di un ENUM, come quella di una struttura, non alloca nulla in memoria. La allocazione viene eseguita solo quando viene dichiarata una variabile che non sia nello stack. In C comunque un ENUM ha solo valori interi (come dice il nome, ossia è una enumerazione).
 
  • Mi piace
Reactions: demda

demda

Utente Attivo
Ah, qui entriamo in un campo difficile: memory packing. Il compilatore C assegna ad ogni campo della struttura un numero di byte in modo da renderne più facile l’accesso, aggiungendo byte qua e là. Per esempio anche se dichiari un dato char o specifichi un numero preciso di bit, il compilatore effettuerà un “padding” aggiungendo byte in modo che l'offset del campo successivo sia un numero pari o, più comunemente, un multiplo di 4 (ossia 32 bit). Ma non esiste uno standard, ogni compilatore implementa il proprio padding. Per accedere a un campo della struttura usando un puntatore puoi usare l'operatore Offsetof.

Per quanto riguarda lo spazio degli ENUM, non esiste uno standard, più probabilmente viene usato il int in quanto è l'intero di default. Ricorda comunque che la descrizione di un ENUM, come quella di una struttura, non alloca nulla in memoria. La allocazione viene eseguita solo quando viene dichiarata una variabile che non sia nello stack. In C comunque un ENUM ha solo valori interi (come dice il nome, ossia è una enumerazione).
Stiamo divagando troppo nel tecnico e non sono ancora pronto per questo, mi mancano ancora molti concetti. Mi ritengo più che soddisfatto della risposta ottenuta
Grazie mille

Inviato da Mi A2 Lite tramite App ufficiale di Tom\'s Hardware Italia Forum
 
  • Mi piace
Reactions: Andretti60
Stato
Discussione chiusa ad ulteriori risposte.

Entra

oppure Accedi utilizzando