Newsgroup: it.comp.lang.c
Titolo: Singoli bit

Salve, sto facendo un programma in dos che utilizza il modo 13h.
In questo modo ogni pixel e' rappresentato da un byte.
E fin qui tutto a posto.
Il problema e' che devo mantenere in memoria (non a video) delle immagini
che usano un solo bit per pixel e, utilizzando un char che e' il piu'
piccolo,
spreco un sacco di memoria.
Siccome in C non esiste un tipo BOOL come si pu. utilizzare un solo bit per
volta?
So che c'e' un modo per utilizzare ogni singolo bit del tipo di variabile
dichiarata, ma non so come si faccia.
Per esempio, utilizzando ogni singolo bit fino ad arrivare ad 8 e quindi
formare un char.
Altrimenti c'e' qualche altro metodo?
Grazie a tutti.
Ciao


ICQ #34602650

 


 formare un char.
No, devi formare almeno un int.
struct campo di bit{
    int    bit0:1;
    int    bit1:1;
    int    bit2:1;
    int    bit3:1;
    int    bit4:1;
    int    bit5:1;
    int    bit6:1;
    int    bit7:1;
    int    bit_da_8_a_15:8;
}




Non è che potreste farmi un esempio di settaggio e lettura di un bit?
Poniamo che un int sia di 2 byte. Inoltre il bit più significativo sia il
bit che identificheremo con il numero più alto: quindi, da sinistra a
destra, avremo il 16esimo, il 15esimo... fino al primo.
int var=0x0F00, value=0;
/*la configurazione di var è 00001111 00000000*/
/*pongo a 1 il bit numero 6 - lasciando invariati gli altri*/
var = var | 0x0020;
/*pongo a 0 il bit numero 6 - lasciando invariati gli altri*/
var = var & (~0x0020);
/*ora leggo*/
/*leggo il bit numero 9*/
value = var & 0x0100; /*1*/
/*leggo il bit numero 2*/
value = var & 0x0002; /*0*/
Utilizzi i numeri in formato esadecimale perchè più comodi. Ogni cifra di un
numero esadecimale utilizza 4 bit: utilizzando per ogni cifra i soli valori
1, 2, 4, 8 puoi controllare i 4 bit.
0x0001 = 0000 0000 0000 0001
0x0002 = 0000 0000 0000 0010
0x0004 = 0000 0000 0000 0100
0x0008 = 0000 0000 0000 1000
e così via.
In alcuni casi, al posto della scrittura esplicita del numero in formato
esadecimale si utilizzano delle enumerazioni, tipo
enum flag {
    noflag,
    flag1    =0x0001,
    flag2    =0x0002,
    flag3    =0x0004,
    flag4    =0x0008,
    flag5    =0x0010,
...
};
O almeno io faccio così. Colgo l'occasione per un confronto con eventuali
altri metodi.
--
Francesco Trotta
http://space.tin.it/computer/ftrotta
Elimina "x_" dal mio indirizzo per mandarmi
un messaggio direttamente



 
io userei una union:
	union _bit {
	   char byte;
	   unsigned bit[8] : 1;
	} vettore [lunghezza];
In questo modo puoi usare vettore sia come array di char, che riferirti
bit per bit ad esso.
bye!
-- 
Emanuele Cesena                 
http://www.penguinpowered.com/~ecesena
ece...@penguinpowered.com
                 Attenti all'antispam NOSPAM
- Qual e' l'ape che invece del miele fa la cioccolata?
- L'ape-rugina.
		-- Da it.hobby.umorismo

#include <stdio.h>
struct campo di bit{
    int    bit0:1;
    int    bit1:1;
    int    bit2:1;
    int    bit3:1;
    int    bit4:1;
    int    bit5:1;
    int    bit6:1;
    int    bit7:1;
    int    bit_da_8_a_15:8;
}intero_16_bit;
main (){
/*Ora imposto a 1 il primo bit */
intero_16_bit.bit0 = 1;
/* ora imposto vari altri bit */
intero_16_bit.bit1 = 1;
intero_16_bit.bit2 = 0;
intero_16_bit.bit3 = 1;
/* I campi con piu' di un bit possono accettare valori da 0 a 2^n con
n=numero di bit
   in questo esempio li imposto tutti a 1 */
intero_16_bit.bit_da_8_a_15 = 127;
/* Se specifico che è di tipo signed int (si puo' fare se piu' di 1 bit)
posso anche scrivere */
intero_16_bit.bit_da_8_a_15 = -1;
/* In tutte le istruzioni uso la stessa sintessi */
if (intero_16_bit.bit0 == 1)
    printf ("Il primo bit è attivo\n");
else
    printf ("Il primo bit non è attivo\n");
}
E' più chiaro? Ovvio che ci sono altri metodi, come quello esposto da
Francesco, che in alcuni casi è più adatto.
In teoria dovresti avere una union in modo da poter decidere la lunghezza in
bit che ti serve.
Traccia: una union che ha una maschera di bit come quella che ho descritto e
un int (o un char, o quello che ti serve). Setti i bit usando la maschera, e
scrivi i dati (o li mandi all'Int 13) usando l'altra struttura.
--
Alessandro Monti

 	   unsigned bit[8] : 1;
In C gli array  di bit non esistono!

OK, adesso č tutto chiaro.
Grazie a tutti.


you wrote :
#No, devi formare almeno un int.
Perche' ?
Puo' benissimo utilizzare un char come buffer di 8 pixel.
--------------------------------------------------------
* Andrea Laforgia        (
andrea_...@bigfoot.com
) *
--------------------------------------------------------

> #No, devi formare almeno un int.
Cosě almeno mi ricordo dall'help del mio vecchio compilatore Turbo C.
Comunque mi sembra che sia lasciato all'implementazione del compilatore, ma
(sempre se la memoria non mi inganna) la dimensione minima č quella di un
int.
In particolare mi riferisco alla struct come maschera di bit; altri hanno
proposto, forse piů giustamente, di usare le operazioni di shift per
indirizzare i singoli byte, applicabile a tutti i tipi ordinali e forse piů
controllabile (anche se una volta era sconsigliata perchč meno portabile)

destra, avremo il 16esimo, il 15esimo... fino al primo.
[omissis]
Riguardo al metodo da me riportato, non so se possa essere pertinente
o meno, ma, se non erro, in C++ i campi di bit non esistono (a
proposito di differenze C e C++ :-). Quindi, l'altra scelta non
sarebbe eventualmente portabile.
_____________________________________________________
Francesco Trotta
http://space.tin.it/computer/ftrotta
elimina "x_" dal mio indirizzo per le risposte


Non con i bit field. Non so cosa dica lo standard, ma tutti i
compilatori che ho usato fino ad ora arrotondano le strutture con bit
field a int, per cui:
typedef struct {
  unsigned int bit0: 1;
  .....
 unsigned int bit7: 1;
} bite_t;
sizeof(bite_t)==sizeof(int), e
bite_t bytearray[5];
&bytearray[0]==&bytearray[1]+sizeof(int)
Quindi i bit field non sono adatti, anche perche non e' garantito
l'ordine di allocazione. bit0 potrebbe benissimo corrispondere al bit
piu' significativo (0x8000 con in a 16 bit), anche se e' veramente
difficile che a qualcuno venga in mente di scrivere un compilatore che
allochi i bit field rovesciati.
Saluti, Alberto.

 sarebbe eventualmente portabile.
Mi sa che erri.
EMG

 non esistono (a proposito di differenze C e C++ :-). 
  Fino alla versione 2 draft dello standard c'erano (cfr. Stroutrup
corrispondente). Li hanno eliminati nel seguito? Sebbene poco usati, non
li vedevo cosi` inutili...
	Alla prossima,
		Marco

you wrote :
#> #No, devi formare almeno un int.
#Cosě almeno mi ricordo dall'help del mio vecchio compilatore Turbo C.
#Comunque mi sembra che sia lasciato all'implementazione del compilatore, ma
#(sempre se la memoria non mi inganna) la dimensione minima č quella di un
#int.
Che la dimensione dell'int dipenda dalla lunghezza della parola
macchina e' assodato, ma questo non significa che esso sia il tipo
"minimo" da utilizzare nel proprio codice.
#In particolare mi riferisco alla struct come maschera di bit; altri hanno
#proposto, forse piů giustamente, di usare le operazioni di shift per
#indirizzare i singoli byte, applicabile a tutti i tipi ordinali e forse piů
#controllabile (anche se una volta era sconsigliata perchč meno portabile)
L'utilizzo di un "char" elimina i problemi di portabilita',
evidentemente legati al diverso "endianess" delle diverse macchine.


you wrote :
#> #No, devi formare almeno un int.
#>
#> Perche' ?
#> Puo' benissimo utilizzare un char come buffer di 8 pixel.
#>
#
#Non con i bit field.
Chi sta parlando di "bit field" ?? io sto parlando di "tipo" char


Mi sa che erri.
Il seguente listato
---------------------------------------------------
struct campibit {
	campo1:1;
	campo2:1;
	campo3:1;
};
int main()
{
	struct campibit prova;
	return 0;
}
--------------------------------------------------
Viene compilato correttamente come programma C, ma non come programma
C++. Il compilatore utilizzato č il Borland Turbo C++ 1.0.


 evidentemente legati al diverso "endianess" delle diverse macchine.
Se usi un char alla volta, non si pone il problema, ma se ne usi più di uno
alla volta, si. Per questo sono stati inventati i campi di bit.
Proprio per decidere con sicurezza l'ordine dei bit in strutture più grandi
di 1 byte. Ti faccio notare che l'ordine di memorizzazione delle variabili è
lasciata al compilatore, persino gli array potrebbero essere allocati in
ordine inverso. Le strutture, anche se composte da singoli byte, potrebbero
decidere di allineare ogni campo agli indirizzi pari, sprecando spazio ma
magari aumentando la velocità d'accesso. L'unica cosa che è garantita è la
correttezza delle operazioni che ci fai, e un'operazione sui singoli bit è,
in generale tra quelle per cui si garantisce ben poco.
In realtà il compilatore potrebbe benissimo decidere di usare un formato BCD
per gli interi, senza uscire dallo standard, e in questo caso le usuali
operazioni sui bit hanno un significato ben diverso...
Il problema dell'ordine dei byte è tutt'altra cosa, e in altri linguaggi è
stata risolta imponendo un certo formato (java prima di tutti), in C è
compito del programmatore.
--
Alessandro Monti

 };
Non te lo compila perchč non hai messo il tipo. Lo so che č scontato che sia
unsigned int, ma nondimeno č necessario.
Prova con:
 struct campibit {
 int campo1:1;
int campo2:1;
int campo3:1;
 };
Vedrai...
--
Alessandro Monti

 C++. Il compilatore utilizzato è il Borland Turbo C++ 1.0.
Non ti pare di utilizzare un compilatore un po' vecchiotto per provare
la tua tesi?
EMG

 
ops... allora:
	struct _bits {
	   unsigned b1 : 1;
	   unsigned b2 : 1;
	   unsigned b3 : 1;
	   unsigned b4 : 1;
	   unsigned b5 : 1;
	   unsigned b6 : 1;
	   unsigned b7 : 1;
	   unsigned b8 : 1;
	}
	union _bit {
	   char byte;
	   struct _bits bit;
	}
bye!
-- 
Emanuele Cesena                 
http://www.penguinpowered.com/~ecesena
ece...@penguinpowered.com
                 Attenti all'antispam NOSPAM
- Pronto, Polizia?  Vorrei denunciare un furto.  Poco fa sono salito in
  auto, ed ho visto che mi hanno rubato il cruscotto, il volante, la
  leva del cambio e tutti e tre i pedali!
(Dopo dieci minuti...)
- Pronto, Polizia?  Sono quello di prima.  Lasciate stare.  Per sbaglio
  mi ero seduto sul sedile posteriore...

int campo3:1;
Hai ragione


you wrote :
#struct campibit {
#	campo1:1;
#	campo2:1;
#	campo3:1;
#};
#Viene compilato correttamente come programma C, ma non come programma
#C++. Il compilatore utilizzato č il Borland Turbo C++ 1.0.
Ma non mancano gli identificatori di tipo davanti a campoX ?
Comunque con Borland C++ 5.02 viene compilato correttamente come
sorgente C++.


la tua tesi?
Non pensavo fosse così vecchio da essere fuori standard!


you wrote :
#Se usi un char alla volta, non si pone il problema, ma se ne usi più di uno
#alla volta, si. Per questo sono stati inventati i campi di bit.
<snip>
Non capisco perche' ogni cosa deve essere complicata.
Si sta parlando di un char come buffer di almeno 8 pixel, non credo
che la cosa sia cosi' difficile da capire.
#Il problema dell'ordine dei byte è tutt'altra cosa, e in altri linguaggi è
#stata risolta imponendo un certo formato (java prima di tutti), in C è
#compito del programmatore.
L'allineamento dei byte in memoria e' determinato dalla piattaforma
utilizzata, non dal programmatore.


 utilizzata, non dal programmatore.
Il problema dell'ordine dei byte è tutt'altra cosa, e in altri linguaggi è
stata risolta imponendo un certo formato (java prima di tutti), in C è
compito del programmatore risolvere il problema dell'ordine di byte da una
piattaforma all'altra.
Concordo che per i singoli byte il problema non sussiste, mi sono riletto il
primo post.
--
Alessandro Monti

 Non pensavo fosse così vecchio da essere fuori standard!
No, magari per il C va benissimo. Ma dato che si parlava di una
caratteristica del C++ allora diventa vecchissimo dato che lo standard
del C++ è molto recente e praticamente nessun compilatore vi è ancora
perfettamente conforme, neanche quelli della GNU che vengono
costantemente aggiornati.
EMG

Non pensavo fosse così vecchio da essere fuori standard!
E' molto fuori standard, sia C che C++.
Ciao, Giuseppe
---------------------------------------------------------------------------
_Guybrush su IRCNet canale #programmazione
ICQ: 42227764
---------------------------------------------------------------------------