Newsgroup: it.comp.lang.c
Titolo: Bit field

Salve, nel codice in fondo al messaggio, ho dichiarato all'interno della 
struttura dei BIT-FIELD
Ho poi fatto in modo di capire quanta "memoria" occupano ..
Mi aspetterei che 8 bit occupassero 1byte, invece occupano .. 8 BYTE!!!
(verificato con 2 compilatori, uno dei quali è il GCC,l'altro LABWINDOW di 
National instruments)
Inoltre se aumento i campi da 1 a 6,non cambia nulla in termini di spazio 
occupato
esempio ..
unsigned B00:6;
Per finire non cambia nulla se scrivo:
unsigned char B00:1;
Come è possibile?
##########################################
#include <stdio.h>
#include <stdlib.h>
int main()
{
    struct
    {
     char tipo[6];
     float potenza;
     unsigned int numerogiri;
     float alimentazione;
     unsigned B00:1;
     unsigned B01:1;
     unsigned B02:1;
     unsigned B03:1;
     unsigned B04:1;
     unsigned B05:1;
     unsigned B06:1;
     unsigned B07:1;
     unsigned int fine;
    } Dinamo = {"D2001",1200.0,3300,100.0,1,0,1,0,1,0,1,0,50};
    printf("\n\t\tIndirizzi e valoriu dei membri in struttura\n");
    printf("\nIndirizzo = %p:",&Dinamo.tipo);
    printf(" Tipo=%s", Dinamo.tipo);
    printf("\nIndirizzo = %p:",&Dinamo.potenza);
    printf(" Potenza=%f", Dinamo.potenza);
    printf("\nIndirizzo = %p:",&Dinamo.alimentazione);
    printf(" Alimentazione=%f", Dinamo.alimentazione);
    printf("\nIndirizzo = %p:",&Dinamo.fine);
    printf(" Fine=%i", Dinamo.fine);
    return 0;
}
}

Mi aspetterei che 8 bit occupassero 1byte, invece occupano .. 8 BYTE!!!
Nel creare dei campi bit tu chiedi solo di mappare i bit, non imponi
specifici requisiti di memoria. In sostanza non sta scritto da nessuna
parte che il campo bit debba occupare esattamente un bit. Anzi, è più
probabile che il sistema lo mappi sul tipo con cui lavora più
comodamente.

 Mi aspetterei che 8 bit occupassero 1byte, invece occupano .. 8 BYTE!!!
Lo standard del linguaggio invece dice che ogni compilatore e' libero
di disporre i campi di una struct nel modo che preferisce, lasciando
anche dello spazio se rende piu' efficente l'accesso.
Lo stesso effetto lo trovi se dichiari campi di char: puoi ottienere
che un tipo struct con due campi char occupi 8 byte invece di 2!
In genere i vari compilatori forniscono delle estensioni per "impaccare"
i tipi struct in modo da non lasciare spazio in mezzo, consentendo 
quindi di scrivere tipi struct che abbiano una disposizione definita
dal programmatore, in genere si tratta di istruzioni tipo
"#pragma pack()" o __attribute(packed) o qualcosa del genere.
Per il gcc puoi consultare il link:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
ciao
Giacomo

 Come è possibile?
Come ti hanno già risposto l'occupazione di memoria dipende dal compilatore.
Se ti serve la certezza che 8 bit occupino un solo unsigned char l'unico 
modo che mi viene in mente è usare gli operatori &,|,^ e ~ (oltre agli 
shift ovviamente).
Remo.D


Ciao a tutto il NG,
scusate se riprendo l'argomento ma la curiosit� ...
In sostanza affermate che non ci si pu� fidare nemmeno in questo modo?
f()
{
    static union {
        struct {
                unsigned char b0:1;
                unsigned char b1:1;
                unsigned char b2:1;
                unsigned char b3:1;
                unsigned char b4:1;
                unsigned char b5:1;
                unsigned char b6:1;
                unsigned char b7:1;
               } s;
        unsigned char ba;
    } u;
    u.s.b1 = 1;
    printf("%d %d", 
u.ba
, sizeof(u));
}
Un saluto,
Maxime. 

dMaxime ha scritto:

Partiamo da quello che dice lo standard (6.7.2.1-10):
An implementation may allocate any addressable storage unit large enough 
to hold a bitfield. If enough space remains, a bit-field that 
immediately follows another bit-field in a structure shall be packed 
into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or 
overlaps adjacent units is implementation-defined. The order of 
allocation of bit-fields within a unit (high-order to low-order or 
low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
Se capisco bene, lo standard prevede solo che i bit field vengano 
"impacchettati" il piu' possibile nelle "allocation unit".
Se per il tuo compilatore/architettura la minima "allocation unit" � 16 
bit (per esempio per garantire che gli indirizzi siano pari, come 
accadeva nella famiglia 68000) la struttura s sar� lunga almeno 16 bits.
Inoltre lo standard indica che i bit saranno contigui nell'allocation 
unit ma dice esplicitamente che l'ordine con cui i bit vengono 
memorizzati � "implementation defined" quindi, anche se la struttura s 
del tuo esempio fosse 8 bit, 
u.ba
 potrebbe essere 2 (00000010) oppure 64 
(01000000).
C'e' un motivo specifico per voler usare i bit-fields?
Secondo me l'unico caso in cui ha senso � quando si scrive codice 
embedded per un determinato processore e quindi si sa con certezza come 
verranno mappati i bit. Ma in questo caso non ha senso guardare lo 
standard, il manuale del processore/compilatore fa testo!
Remo.D

 64 (01000000).
Potrebbe, ma non sarebbe molto efficiente ne' logico.
B.

 
Hai ragione brix, il passo che ho riportato � del C99 ma, ai fini della 
dimensione non cambia molto. Al massimo nel C89 si occuper� piu' spazio.
Anche l'esempio del 68K puo' non essere determinate perche' l'accesso al 
singolo byte � possibile anche su indirizzi dispari (ovviamente).
Mi sono andato a rileggere lo standard (ovviamente saltando qua e la') e 
forse "allocation unit" � usato nel senso di "minimal storage unit" e 
quindi 8 bitfields da 1 bit verrebbero memorizzati in un char. 
Naturalmente un char puo' avere piu' di 8 bit, ma questo � un'altro 
problema.
D'altra parte, pero', l'unico vincolo su un "bit" � che sia abbastanza 
grande da contenere i valori 0 e 1.
E poi c'e' sempre il problema dell'ordine con cui i bit vengo 
memorizzati (anche se "invertire" l'ordine di memorizzazione non e' 
logico, e' pur sempre possibile).
La mia domanda e': vale la pena scrivere codice basato su una serie di 
ipotesi incerte?
Secondo me, se l'obiettivo � memorizzare 8 bit in un byte tanto vale 
lavorare con gli operatori sui bit, se invece l'architettura target ha 
operatori specializzati a lavorare su gruppi di bit meglio far 
riferimento al manuale del processore e del compilatore.
Remo.D

 unsigned char bf3:3;
:-)
E' qui che vi volevo. Secondo la mia opinione, i bit field sono stati 
implementati per non rendere il codice legato alle caratteristiche del 
uProcessore e, quindi, non rischiare probemi con l'utilizzo degli 
operatori-bit (>>, <<, &, |, ...). Negli esempi che mi state riportando, 
comunque, le struct non sono racchiuse in union.
P.S.: se sulle vostre macchine non funziona ... avvisatemi per cortesia.

 P.S.: se sulle vostre macchine non funziona ... avvisatemi per cortesia.
Pensavo volessi sapere se funziona *in generale*, non nel nostro caso 
specifico.

 specifico.
Certo, seguendo il tuo filo preferirei anchio un'informazione esaustiva ma 
se mi aveste risposto che la union, sulle vostre macchine, occupa ugualmente 
8 byte anzich� ridurre l'occupazione, allora avrei approfondito l'argomento.
Un saluto,
Maxime. 

 
Veramente l' occupazione di una struttura non e'
correlata ai bit field ;-)
In generale il compilatore allinea i dati delle
strutture nella maniera piu' comoda: in questo caso
si suppone che le strutture siano allineate a 8 byte
quindi si ha uno 'spreco' di 7 byte quando nella struttura
compare un solo elemento di un char: pero' tutti i
compilatori permettono la possibilita' di impaccare
i dati delle struttune nel numero esatto di componenti.
Con windows si usa la diretiva pack(1) [vado a memoria]
per forzare l' allineamento al byte, con lo gnu
si usa la direttiva  __attribute__((packed)) .
Comunque verifica con il tuo compilatore (Data allignment)
e vedrai che l' occupazione delle strutture si riduce
a quanto atteso ;-)
B.