dostanie sie do adresu pamięci zmiennej

0

Problem jest taki :
Potrzebuje po wpisaniu liczby zmiennoprzecinkowej podczas programu dostać jej wartość w systemie binarnym;
Czy jest możliwe dostanie sie do pamięci w ktorej zarezerwowane jest miejsce dla zmiennej i odczytanie jej ? Bo podobno
dane zapisywane tam są w systemie binarnym.
Czy wykonanie takich króków jest możliwe ? :
1.wczytanie zmiennej,
2.odczytanie adresu pamieci zmiennej poprzez $a,
3.dostanie sie pod adres zmiennej,
4.odczytanie bajt po bajcie zmiennej i wpisywanie do innej zmiennej,(16 bitów ? ),
5.wyswietlenie tej zmiennej.
Prosze o wyrozumiałość mogłem niedokładnie opisać swój problem lub źle podejść do wyciagania tych danych.
Z góry dziękuje za pomoc. Pozdrawiam

0

I nie prosze o kod tylko o wskazanie drogi bo mogłem źle zrozumieć cały proces deklarowania zmiennych i zapisywania ich w pamieci .

0

Tak, da się to wszystko zrobić. Najłatwiej to chyba zrobić unią które C wspiera z tego co się orientuję.

Np. tutaj masz jak to się robi:
http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx

Jeżeli chodzi o ręczne kopiowanie, to też się da za pomocą operatora wyłuskania i memcpy

0

Trochę przerobisz i będzie ok.

#include <iostream>
void printBinary(const unsigned char val){
    for(int i=7;i>=0;i--){
        if(val &(1<<i))
            std::cout<<"1";
        else
            std::cout<<"0";
    }
}

int main(){
    int n=100;
    printBinary(n);
    return 0;
};
1

Zmienna zmiennoprzecinkowa to po prostu zbiór bitów. Nie musisz nic konwertować. Aby dostać się do konkretnych bitów / bajtów wystarczy rzutowanie na typ całkowity:

#include <iostream>
using namespace std;

typedef unsigned long long ull; // 64-bit, sorry, nie wiem jak jest w C

void PrintBits(ull value, unsigned start, unsigned count)
{
	ull mask = 1ULL << start;

	while (count-- > 0) {
		cout << ((value & mask) != 0) ? '1' : '0';
		mask >>= 1;
	}
}

int main()
{
	double var;

	while (cout << "Podaj wartosc zmiennej: ", cin >> var) {

		ull *bits = (ull*)&var; // <----------- RZUTOWANIE

		cout << "znak  cecha           mantysa" << endl;
		PrintBits(*bits, 63, 1);
		cout << "     ";
		PrintBits(*bits, 62, 11);
		cout << "     ";
		PrintBits(*bits, 51, 52);
		cout << endl;
	}
}

Generalnie zasada jest taka, że najpierw rzutujesz na tym całkowity (jeśli typ wyjściowy nie jest takowym), a później przy pomocy operacji bitowych (>>, <<, &, ...) dostajesz się do konkretnych bitów/bajtów. Aby uniknąć pułapek z data alignment, typ całkowity na który rzutujesz musi być nie większy (w sensie sizeof) niż typ wyjściowy.

Przy takich rzeczach trzeba uważać na pułapki związane z data alignment/padding oraz endianem.

0

Witam,
Program wygląda tak :

 //binarnie
#include <stdio.h>

void main(int argc,char *argv[])
{
	//liczenie dla liczby dziesietnej
	int i;
	int rozmiar=8*sizeof(float);
	char * n[rozmiar+1];
	float a=6.23;
	printf("Nazwa programu %s\n",argv[0]);
		for(i=rozmiar;i>=0;i--){
		if (((int)a & 1)==1) n[i]="1";
		else n[i]="0";
		a=(int)a>>1;
	}
	for(i=0;i<=rozmiar;i++){
		if (i==0) printf("%s-",n[i]);
		else if (i==8) printf("%s.",n[i]);
		else printf(n[i]);
	}
	// koniec 1 programu 


	
	

	getchar();
}

a wynik jak w załączniku . Wzorowałem sie na rysunku //upload.wikimedia.org/wikipedia/commons/2/2e/IEEE-754-single1.svg

0

Jaki błąd popełniłem ??

0

Wiele. Po pierwsze, popraw wcięcia, bo trudno śledzić twoje pętle.
Po drugie, zapis (int)a po prostu obcina ci część ułamkową, zostawiając całkowitą.
Żeby dostać się do bitów floata, użyj unii.

0

a teraz ?

<code class="c"> 

// binarnie
#include <stdio.h>

void main(int argc,char *argv[]){
float a;

int i;
int rozmiar=8*sizeof(int); //rozmiar int 4 bajty 1 bajt 8 bitow
char *n[rozmiar];
int maska=1; // binarnie 00000001



// wczytanie zmiennej float
printf("Podaj liczbe zmienno przecinkowa:");
scanf("%f",&a);


// rzutowanie a na long by móc robic operacje bitowe;
long b = *(long *)(&a);

for (i=rozmiar-1;i>=0;i--,b>>=1) {//przesuwa b o jedno miejsce prawo by porownac nastepny bit
if ((b & maska)==maska) n[i]="1";//porownuje bit z ostatnim maski bo 1 to 00000001
else n[i]="0";

}
printf("znak cecha mantysa \n"); // w 32 bitach 1 to znak kolejne 8 cecha nastepne to mantysa
for(i=0;i<rozmiar;i++)
{
if (i==0) printf(" %s ",n[i]);//jesli znak 1 to ujemne jesli 0 dodatnie
else if (i==1) printf(" %s",n[i]);//ułamek
else if (i==8) printf("%s ",n[i]);//ulamek
else printf(n[i]);//wykladnik
}
getchar();
getchar();
}

0

Teraz jest ok. Można jeszcze dopieścić parę rzeczy. Jak long to long a nie raz int a raz long. Zamiast tablicy łańcuchów (n) użyć tablicy pojedynczych znaków. Ze stałych zrobić define'y.

I jeszcze taka rada - jeśli chodzi nam o bity (np. maski bitowe) to dobrą konwencją jest używać zapisu szesnastkowego liczb. Np. u ciebie maska to 1 - warto ją zapisać w postaci 0x00000001. Taki zapis sugeruje właśnie, że chodzi o liczbę, w której ustawione są konkretne bity.

#include <stdio.h>

#define ROZMIAR (8 * sizeof(long))

// binarnie 00000001
#define MASKA 0x00000001 

void main(int argc,char *argv[])
{
	float a;

	int i;
	char n[ROZMIAR];

	// wczytanie zmiennej float
	printf("Podaj liczbe zmienno przecinkowa:");
	scanf("%f", &a);

	// rzutowanie a na long by móc robic operacje bitowe;
	long b = *(long *)(&a);

	for (i = ROZMIAR - 1; i >= 0; i--, b >>= 1) { //przesuwa b o jedno miejsce prawo by porownac nastepny bit
		n[i] = ((b & MASKA) != 0) ? '1' : '0'; //porownuje bit z ostatnim maski bo 1 to 00000001
	}

	printf("znak  cecha          mantysa \n"); // w 32 bitach 1 to znak kolejne 8 cecha nastepne to mantysa
	printf("%.1s %.8s %.23s", n + 0, n + 1, n + 9);
	getchar();
	getchar();
}
0
        float a;
        long b = *(long *)(&a);

To jest, ściśle rzecz biorąc, undefined behavior w C99 (dozwolone jest w C++).
Dlaczego — szukaj: strict aliasing.

Przy włączonej optymalizacji kompilator C ma prawo zdetonować twój program na takim kodzie.

0

Ale to dopiero przy użyciu restricted, czyż nie?

0

Bezpiecznie można rzutować na char * w C, w tym wypadku (i o ile dobrze pamiętam tylko dla char *) strict aliasing nie ma znaczenia.

0

mógłby mi ktos wytlumaczyc dzialanie tego kodu ?:
n[i] = ((b & MASKA) != 0) ? '1' : '0';
to cos w stylu if else ?

0
n[i] = ((b & MASKA) != 0) ? '1' : '0';

if((b & MASKA) != 0) {
  n[i] = 1;
} else {
  n[i] = 0;
}
0

czyli zamiast int b=(int)&a wystarczy zrobic tak ?

#include <stdio.h>
union{
float f;
int i;
}u;
void main(void){
        printf("Podaj liczbe zmienno przecinkowa:");
        scanf("%f",&u.f);
        b=u.i; 
}

tak ?

0

Tak, tylko zadeklaruj b, bo tego nie zrobiłeś

0

no tak tak :)

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