在Ubuntu下,比葫蘆畫瓢,寫了一個程序,居然報錯!!!!
1 #include <stdio.h> 2 3 float i = 3; 4 int j = *(int *)(&i) ; 5 6 int main (int argc , char *argv[]) 7 { 8 printf( "i = %f \n" , i ) ; 9 printf( "j = %#x \n" , j); 10 return 0; 11 }
對於高手,一眼就能看出其中的問題,不過對標准C語言不是很明白的可能就搞不清楚了。
編譯,gcc -o text text.c、./text,出現如下錯誤:
1 text.c:4: error: initializer element is not constant
其中原因在於: C語言初始化一個全局變量或static變量時,只能用常量賦值,不能用變量賦值!上面的代碼第3行的i是個變量,於是第4行出錯。這里注意,即使第3行用const int a = 100,編譯器也視a為變量。
解決方法一:
1 #include <stdio.h> 2 3 float i = 3; 4 5 int main (int argc , char *argv[]) 6 { 7 int j = *(int *)(&i) ; 8 printf( "i = %f \n" , i ) ; 9 printf( "j = %#x \n" , j); 10 return 0; 11 }
解決方法二:
對於i使用:
1 #define i 3
不過這就失去了我的本意了,你懂的~
好吧,這個程序是驗證浮點型在內存中,如何表示的,以下為轉載,互聯網就是偉大!!!
單精度浮點數: 1位符號位 8位階碼位 23位尾數
雙精度浮點數: 1位符號位 8位階碼位 52位尾數
實數在內存中以規范化的浮點數存放,包括數符、階碼、尾數。數的精度取決於尾數的位數。比如32位機上float型為23位 double型為52位。
單精度float型存儲在內存中的大小為4個字節,即32位。
浮點表示的一般形式為:R=M*2^e (R:Real M:Mantissa尾數 e:exponent階碼)
把上面float的二進制可分成三部分:
x xxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx
數符(1b) 階碼(8b) 尾數(23b)
double型的浮點數分別是:數符(1b)、階碼(8b)、尾數(52b)
數符sign:real的正負號 "+":0 "-":1
階碼e:e=E-127(double型中e=E-1023) e為正值說明這個浮點數向左移動了e位, e為負值說明這個浮點數向右移動了e位。127=2^7-1 1023=2^10-1
尾數M:有效數字位,這里是有效數字位的部分二進制碼
例1:float型浮點數125.5轉化成32位二進制浮點數
125.5的二進制碼為1111101.1,寫成二進制的科學計數為:1.111101*2^6(因為科學計數法“整數”部分大於1,在二進制中,“整數”部分只能恆為1)即向左移6位,則e=6,則E=e+127=133,而E的二進制碼為10000101,而1.111101把“整數”部分去除1之后為111101,之后補0,共23b,形成了階碼。
所以125.5的32位二進制浮點數為
0 10000101 11110100000000000000000
例2:float型浮點數0.5轉化成32位二進制浮點數
0.5的二進制碼為0.1,寫成二進制的科學計數為:1.0*2^(-1)即向右移1位,則e=-1,則E=e+127=126,而E的二進制碼為01111110,而1.0把“整數”部分去除1之后為0,之后補0,形成了階碼。
所以0.5的32位二進制浮點數為
0 01111110 00000000000000000000000
double型浮點數類似。
例3:32位二進制浮點數為0 10000010 00010000000000000000000轉化成十進制數浮點數
題中已給我們分了三部分,數符部分、階碼部分、尾數部分。
數符部分為0,則代表此數為正數;階碼部分為10000010,則E=130,則e=E-127=3,則說明其向左移了3位,0001加上“整數”部分的1之后,為1.0001。則原二進制數為1000.1=十進制8.5,或R=1.0001*2^3=8.5。
還是清楚原理好呀!
