Newsgroup: it.comp.lang.c
Titolo: perchè????

Perchè questo codice mi da in output 32? Non dovrebbe darmi 5+4+7=16?
struct data{
       unsigned giorno:5;
       unsigned mese  :4;
       unsigned anno  :7;
       }oggi;
 printf("%d\n",sizeof(oggi)*8);

 Perchč questo codice mi da in output 32? Non dovrebbe darmi 5+4+7=16?

Il codice che hai scritto usa estensioni al linguaggio assolutamente non 
standard; strutture di questo tipo sono non portabili e ti sconsiglio 
vivamente di usarle.
A seconda del compilatore e della piattaforma che usi il compilatore
puo' decidere di allineare le boundaries dove e' piu' comodo per lui.
Molto probabilmente nel tuo caso sei su una piattaforma a 32 bit e
quindi il compilatore con molta probabilita', anche se magari ha
impacchettato i bit vicini tra loro, ha deciso di aggiungere un paio
di byte di padding alla fine.
Se proprio ti serve/ci tiene, prova a vedere la doc del tuo compilatore 
(e relativi flag) sull'allineamento della memoria (memory alignment e 
word boundaries).
Se puoi non usare questa sintassi che prima o poi e' destinata a darti 
dei grattacapi. Se proprio devi, impachetta il tutto da solo, per es:
int16  myData;
#define MASK_ANNO 0x007F
#define MASK_MESE 0x0780
etc
e quindi estarre e shiftare i dati come ti serve (usa MACRO ...)
ciao

 word boundaries).
mi spieghi cosa significano tutti questi termini?
per adesso ho risolto il problema in questo modo (dimmi se va bene):
------------inizio codice
    /*impacchetta la data (i 5 bit bassi vanno al giorno, 4 bit al mese e 7
all'anno*/
#define DATA_A_SHORT(giorno,mese,anno) (((anno-1900)<<9)+(mese<<5)+giorno)
    /*estraggono i componenti della data*/
#define EST_GIORNO(short_data) (0x001F&short_data)
#define EST_MESE(short_data) ((0x01E0&short_data)>>5)
#define EST_ANNO(short_data) (((0xFE00&short_data)>>9)+1900)
typedef unsigned short data;
data oggi;
    oggi=DATA_A_SHORT(2,1,2005);
    printf("%d\n",oggi);
    printf("%d %d %d\n",EST_GIORNO(oggi),EST_MESE(oggi),EST_ANNO(oggi));
-------------fine codice

 sconsiglio vivamente di usarle.
Vuoi scherzare? i campi di bit sono C standard e in quanto tali il 
codice e' portabilissimo su qualsiasi piattaforma dotata di un 
compilatore standard.
Giorgio

  printf("%d\n",sizeof(oggi)*8);
???
-- 
Quando noi ignoranti eravamo di piů, tutto era piů bello (A. Celentano).
  ___   _   ___ _  _______   _______ ___
|   \ /_\ | _ \ |/ / _ ) \ / /_   _| __|
| |) / _ \|   / ' <| _ \\ V /  | | | _|
|___/_/ \_\_|_\_|\_\___/ |_|   |_| |___|

 c'azzecca sizeof() con le somme?
Cazzata mostruosa! Scusate :(


 
Hai ragione, ma prova a voler trasmettere la struttura su rete,
o piu' banalmente a volere fare una write su file che
puo' essere acceduto anche da altra macchina
e sicuramente sei obbligato a fare diverse elaborazioni.
per leggere la lunghezza giusta al posto giusto etc.
Se impacchetti, sei sicuro della sizeof e puoi scrivere/leggere con una
sola operazione.

 e sicuramente sei obbligato a fare diverse elaborazioni.
Fra dire questo e dire che i bitfield non sono standard C c'è un abisso. A
questa stregua, nemmeno gli "int" sono standard C.
A fronte di questo semplice codice: 
   int i = 10;
   fwrite(&i, sizeof(int), 1, f);
un compilatore potrebbe scrivere su file questa sequenza di byte:
    0x00 0x0A
mentre un altro potrebbe scrivere questa:
    0x0A 0x00 0x00 0x00 0x00
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 sola operazione.
Ne sei sicuro ?
Mai sentito parlare di big endian, little endian e altro ?
La protabilita' dei file binari non c' e'. Purtroppo :-(
Giorgio

 ha scritto nel messaggio
news:crbtp0$isv$1...@newsfeed.cineca.it...

Quindi mi pare di capire che sia usando strutture con bitfield che valori
impacchettati in un'unica variabile potrei avere dei problemi di
portabilità... Ma se il programma dovesse funzionare solo sul computer su
cui lo scrivo potrei usare indifferentemente una soluzione o l'altra?


Nella mia esperienza di progettazione di sistemi di controllo l'uso dei 
bitfields e` sempre stato molto utile per usare le interfacce HW e per 
descrivere strutture di interfaccia fra macchine diverse.
Credo che molte descrizioni dei pacchetti che viaggiano in rete usino 
questo tipo di strutture, usando poi opzioni del compilatore per 
eliminare gli allineamenti,
Ciao
Giovanni


 cui lo scrivo potrei usare indifferentemente una soluzione o l'altra?
Esatto.
E, alle stesse condizioni, lo stesso programma funzionerebbe senza
modifiche su un altro sistema, a patto ovviamente di ricompilarlo.


 Giorgio
Lo standard dice che deve essere allocato uno spazio sufficiente per 
contenere un bit-fiels e che se rimane abbastanza spazio i bit-fiels 
saranno allocati uno di seguito all'altro.
Nell'esempio del post precedente e` chiarmente un int. Parola non ha 
alcun significato.


 e sicuramente sei obbligato a fare diverse elaborazioni.
Prova a fare la stessa cosa con una banalissima, standardissima, 
variabile di tipo int (hint: byte order).
Questi problemi riguardano gli standard di trasmissione e di formato non 
di codice.


forse è una domanda stupida... ma in memoria verrebbero immagazzinate allo
stesso modo?
esempio:
unsigned short x=0x0003
struct z{
    unsigned y:1;
    unsigned k:2;
    ...
    }
in questo caso i 3 bit bassi di short x sarebbero uguali ai 3 bassi di
struct z? o nella struttura c'è un byte di padding anche tra le prime due
variabili?


Si, ma puoi' sempre definire un formato di scrittura e dire che
per convenzione i dati devono essere scritti in big/small endian.
Usi poi ntohl e simili per fare le conversioni. Se impacchetti usando
l'int ne vieni fuori relativamente bene, se usi la struttura con
i bit field devi elaborare molto di piu'.

 descrivere strutture di interfaccia fra macchine diverse.
Giusto per curiosita', l'endianity e gli allineamenti, ci sei
mai cozzato contro ?  Come appricci il problema ?
- Ciao
- Gio

plato wrote:

Ehm, volevo dire approcci il problema...

 alcun significato.
Nello standard no. Ma io parlavo di implementazioni. E nelle 
implementazioni su architetture concrete "parola" *ha*  un significato.
Altrimenti non si capirebbe perche' lo "spazio" dovrebbe essere proprio 
di 32 bit.
Giorgio

 mai cozzato contro ?  Come appricci il problema ?
Beh... dipende molto da quello che hai a disposizione. Stai lavorando in
rete? Su un dispositivo con ridotte capacita` di calcolo?
Stai lavorando su file? Va bene un file di testo (10 -> "10")? Deve essere
binario? Hai gia` un'applicazione complessa con librerie esterne? (metti
che stai lavorando con GNOME... puoi anche usare libxml)
-- 
[ RiK0                                ]
[ non credo negli schemi non vincenti ]
[ two is an odd prime number          ]


Per quanto riguarda l'allineamento i compilatori usati mi permettevamo 
di eliminare gli allineamenti con la direttiva:
#pragma pack(1)	/* compatta al byte le strutture definite di seguito */
poi la direttiva:
#pragma pack()	/* ripristina l'allineamento di default */
In genere il default e` 2 per compilatori a 16 bits e 4 per compilatori 
a 32 bits.
Per quanto riguarda l'ordine dei byte non ho mai avuto alcun problema 
avendo quasi sempre usato CPU intel (80x86).  Se non ricordo male il 
PowerPC veniva configurato per gestire internamente lo swap dei bytes 
(si comporta come un 80x86), ma ho solo duvuto interfacciarmi senza 
dover sviluppare codice.


 Giorgio


 confusione.  E` piu` corretto chiamarla "dimensione del bus".
Se definisci la parola come l' unita' di base per i trasferimentio di 
informazioni da e per la memoria, ti rendi conto che la dimensione della 
parola coincide con quella del bus.
Per concludere sull' argomento, il concetto di parola (o word) non e' C 
standard ma anche per programmare in C standard e'  utile conoscerlo
(cfr. 
p.es
. 
http://www.cepba.upc.es/docs/ibm_doc/manc/proguide/ref/rvclralg.htm
 )
Ciao
Giorgio

 Ciao


Anche se oramai siamo OT voglio aggiungere un ulteriore commento alla 
risposta che ho dato ieri a Giorgio sul significato di 'word'.  Chi non 
fosse interessato puo` passare oltre.
Dopo aver inviato il post qualcosa mi rodeva dentro, visto che molta 
gente ancora usa il termine word per indicare la dimensione del bus o 
piu` spesso per indicare l'organizzazione della memoria.  Ho cercato 
quindi di vedere se potevo ricostruirne l'origine cercando fra i ricordi 
e quel po` di documentazione che ancora mi e` rimasta.  Giorgio dice che 
forse sono giovane, ma ho iniziato a lavorare coi calcolatori verso la 
fine degli anni '60, studiando e poi modificando un calcolatore 
progettato negli USA dalla casa madre dell'azienda per cui lavoravo in 
quel tempo come progettista di HW.
Molti di voi non ne avranno mai sentito parlare ma la memoria era 
costituita da banchi (matrici) di nuclei di ferrite (8k).  Un nucleo di 
ferrite costituiva un bit e veniva indirizzato selezionando un driver di 
riga ('row') ed un driver di colonna ('column').  Selezionando di 
leggere una riga era possibile ottenere lo stato dei nuclei di tutte le 
colonne.
L'assieme di tutte le colonne di due banchi affiancati ed indirizzati 
contemporaneamente sulla stessa riga veniva indicata come parola 
('word').  E la letteratura di quel tempo usava il termine per definire 
l'assieme dei bit che risultavano leggendo un indirizzo di memoria e 
bufferizzati nel registro di lettura (o che venivano scritti 
contemporanamente dal registro di scrittura).  Non ricordo se gia` fosse 
in uso chiamarla ampiezza del bus ma sicuramente, in termini moderni, 
sono sinonimi.
E forse da questo l'INTEL ha derivata la keyword usata per definire un 
elemento di 16 bits.  Non ho riferimenti sul soggetto per cui questa e` 
solo una mia supposizione.
In un progetto SW di cui mi sono occupato alla fine degli anni '70 su 
una macchina (a 32 bits) era rimasta la terminologia "full word pointer" 
e "half word pointer" per indicare rispettivamente un pointer a 32 o 16 
bits (o in termini di 8086 far/near).
Chiedo scusa a Giorgio di averlo contraddetto cosi` precipitosamente ma 
solo dopo ci ho ripensato.  Essendo passato all'uso dei processori INTEL 
e del C da piu` di venti anni, il termine parola ha completamente perso 
per me quello che era il suo significato originale.  In ambiente INTEL 
su cui ho lavorato usando prima l'assembler poi il C, 'word' ha sempre 
mantenuto il significato di 16 bit indipendentemente dall'ampiezza del 
bus (8 bits per l'8088/80188 o 32 bits per l'80386 e successivi).
Inoltre lo standard C definisce che la dimensione di un int e` quella 
suggerita dall'architettura dell'ambiente di esecuzione senza imporre 
una scelta.  Nel 8088/80188 il bus e` a 8 bits ma l'architettura interna 
e` a 16 bits.  Ho lavorato su microcontrollori con 80386SX (bus di 
memoria di 16 bits, registri interni a 32 bits). Si puo` tranquillamente 
trasferire un eseguibile per 80286 (16 bits in modo protetto) su un 
80486DX (bus di memoria a 32 bits) senza alcuna necessita` di 
ricompilarlo e sicuramente funziona anche sul pentium.
La dimensione dell'int da cosa e` determinata? Dal bus interno o bus 
esterno? O e` una dimensione imposta dal compilatore per scelta di chi 
lo ha realizzato pensandolo orientato ad una specifica macchina?
Per questo ho detto che 'parola' crea confusione perche` non si capisce 
a cosa e` riferita e l'ho ritenuta fuori luogo nella prima risposta. 
Pero` anche lui ha ragione quando dice che parola a volte e` sinonimo di 
ampiezza del bus.
Chiedo scusa al NG e ringrazio a quelli che mi hanno letto fin qui.
