Newsgroup: it.comp.lang.c++
Titolo: scorrimenti bit

Qualcuno sa come si fa a vedere un float o double bit per bit? sono riuscito
con gli interi usando simboli bitwise
ma il compilatore dice che non possono esser usati con numeri float.
Questo è per gli interi:
#include <iostream>
using namespace std;
void PBinary(const long signed int val){
int c=0;
for(int i = 31; i >= 0; i--){  //i= numero di bit(-1) 32 è il massimo per
gli int
if (c==0){
    if(val & (1 << i)){
      cout << " -";c++;}  //il primo bit è per il segno 1='-' 0='+'
    else {
      cout <<" +";
 c++;}
}
else{
    if(val & (1 << i))
      cout << "1";
    else
      cout <<"0";   //10
}
}
}
int main(){
long signed int a;
while (a!=0) {
cout << "Immetti numero decimale da convertire in binario:";  //massimo
(2^31-1)
cin>>a;
PBinary(a); cout<<"\n";
}
}
gia che ci sono qualcuno sa perchè mi da errore se metto il range
massimo(2.147.483.648) +1 il programma va in lopp infinito se invece metto
9.999.999.999 mi "funziona" (il numero binario è sbagliato).

 ma il compilatore dice che non possono esser usati con numeri float.
L'unico metodo per manipolare bit e' quello di accedervi tramite le operazioni
intere. Quindi la questione diventa come accedere alla memoria che rappresenta
un float come se fosse un intero oppure come trasferire i bit che rappresentano
un float in un intero senza modificarli.
In entrambe i casi stai bypassando il typesystem del C++ quindi stai entrando in
un terreno pericoloso, pertanto stai attento.
Alcuni esempi:
float f;
const unsigned char *p = (const unsigned char*)&f;
union AccessFloat {
    float f;
    const unsigned char p[sizeof(float)];
};
unsigned getFloatBits( const float& f )
{
    assert( sizeof(float)==sizeof(unsigned) );
    return *((unsigned*)&f);
}
Nei primi due casi fai attenzione a non andare fuori range nell'accesso
all'array di caratteri. Nell'ultimo non hai questo problema ma non dimenticare
la assert.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 }
Per quanto difficile che accada in pratica, non e' scontato che due
oggetti di tipi diversi siano allineati allo stesso modo, anche se sono
delle stesse dimensioni.
L'unico altro modo garantito dallo standard e' allocare *dinamicamente*
un'array di unsigned char di dimensioni sufficienti, copiarci sopra il
float ed accedere tramite unsigned char.
Nota che in tutti i casi non hai modo di distinguere se tutti i bit che
leggi via unsigned char fanno parte del float, o se ci sono dei bit (o
byte) di padding.
Ciao,
Nicola


 byte) di padding.
Questo e' sicuro. Cosi' come non sai dove sia la mantissa e dove l'esponente a
meno che non ne conosca a priori il formato.


 versione di getFloatBits dove l'allineamento dei tipi e' mantenuto.
No, casti il puntatore a puntatore a float ed assegni il float a questo
puntatore dereferenziato. Poi pasticci coi char.
Ciao,
Nicola

 allocazione.
Da come la ricordo io la cosa sta nell'altro modo. Il discorso dell'allocazione
dinamica e' che se allochi un blocco di dimensione superiore o uguale a quella
di un float, allora e' garantito che sia allineato in maniera tale da poter
contenere un float nei suoi primi byte.
Hai un riferimento (paragrafo) per quello che dici tu?
I miei sono 5.3.4/10 e 
3.7.3.1/2


 I miei sono 5.3.4/10 e 
3.7.3.1/2
Proprio quelli. Me li ricordo perche' ne ho appena discusso su c.l.c++.m
.
Ciao,
Nicola

 allineata in modo da poter contenere un oggetto di un altro tipo.
Direi che lo standard definisce il problema dell'allineamento come un intero
(non nullo) associato ad ogni tipo per cui il tipo stesso e' allineato se
l'indirizzo e' multiplo dell'intero. Pertanto intrinsecamente un tipo con
allineamento I puo' sempre essere sovrapposto correttamente ad un tipo con
allineamento J se J e' multiplo di I. Questo significa che se sizeof(X) e'
multiplo di sizeof(char) un puntatore a char puo' puntare ad un X senza
problemi. Ci sarebbe la vecchia questione sul sizeof(char)!=1 ma fino a che
sizeof(char)==1 direi che qualunque indirizzo (di qualunque oggetto) puo' essere
convertito in un char* senza problemi di allineamento.


 convertito in un char* senza problemi di allineamento.
Queste restano estrapolazioni tue, ma in realta' stai parlando di
comportamento non definito. Lo standard garantisce la corrispondenza di
allineamento solo tra puntatori ad unsigned char e puntatori ad altri
tipi se puntano ad aree di dimensioni adeguate *allocate dinamicamente*.
Un compilatore potrebbe allocare le stringhe di caratteri statiche in
una zona di memoria fatta per essere indirizzata byte per byte, mentre
le altre variabili statiche potrebbero stare in una zona indirizzata a
word.
Lo standard specifica che questo tipo di gestione non puo' essere
utilizzata per la gestione della memoria dinamica.
Ciao,
Nicola

 utilizzata per la gestione della memoria dinamica.
IMO specifica che non puo' essere usata del tutto.
P.S.: approposito, dai un'occhiata a 3.9/4 (o meglio a 3.9 sub da 1 a 5).
