Reinterp_cast - skąd taki wynik?

0

Witam

Zacząłem ostatnio kombinować troche z reinterp_cast i powstał oto taki program:

#include<iostream>
using namespace std;
struct tablica_20 {
	int tab[10];
};
struct tablica_20_f {
	float tab[10];
};
int main() {
	tablica_20 a;
	tablica_20_f *b = reinterpret_cast<tablica_20_f *>(&a);
	cout << sizeof(a) << " " << sizeof(*b) << endl;
	for(int i=0; i<10; i++) {
		b->tab[i] = i+1;
	}
	for(int j=0; j<10; j++) {
		cout << "J: " << a.tab[j] << endl;
	}	
	return 0;
} 

Chciałem nadpisać wartości 'a' przez 'b'. I tu pojawia się problem, o ile dam w tablica_20_f int wszystko działa, a jak jest float to mam dziwne wyniki:

J: 1065353216
J: 1073741824
J: 1077936128
J: 1082130432
......

Skąd się to bierze?

3

Z tego, że liczby stało i zmiennoprzecinkowe są inaczej zapisywane binarnie. Int to zwykła liczba w systemie dwójkowym, ale z floatem już inna zabawa: http://en.wikipedia.org/wiki/Single-precision_floating-point_format
Jak zapisujesz coś jako float, np. liczbę 3. To ona w pamięcie nie będzie wyglądała tak:

00000000 00000000 00000000 00000011

tylko 01000000 01000000 00000000 00000000

 i jak to potem rzutujesz na int tak jak Ty to robisz to wyjdzie zupełnie inna liczba
3

Wtf.

To co tam robisz to undefined behavior, nie wiadomo co ten program zrobi.

UB jest dokładnie tutaj: b->tab[i], ponieważ uzyskujesz dostęp do obiektu a przez wskaźnik, który nie jest typu tablica_20 i dostęp ten nie spełnia żadnego z punktów 3.10.10 w standardzie (tzw. strict aliasing).

0

Abstrahując od UB, załóżmy na chwilę że patrzymy na konkretną implementację :) Załóżmy też optymistycznie że sizeof(int) ma tyle samo co sizeof(float) na twojej maszynie. Wpisujesz do floata kolejne liczby całkowite. Tylko że float zapisuje liczby jako mantysa*2cecha a nie w kodzie U2 tak jak integer. Czemu? Ano bo float 2 to jest float 2.0 i gdzie ta informacja o części ułamkowej być musi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1