如果賦值運算符兩側(cè)的類型不一致,但都是數(shù)值型或字符型時,在賦值時要進行類型轉(zhuǎn)換。
<1> 將實型數(shù)據(jù)(包括單、雙精度)賦值紿整型變量時,舍棄實數(shù)的小數(shù)部分。如i為整型變量,執(zhí)行“i=3.56”的結(jié)果是使i的值為3,在內(nèi)存中以整數(shù)型式存儲。
<2> 將整型數(shù)據(jù)賦紿單、雙精度變量時,數(shù)值不變,但以浮點數(shù)形式存儲到變量中,如將23賦值紿float變量f,即f=23,先將23轉(zhuǎn)換成23.00000,再存儲在f中。如將23賦紿double型變量d,即d=23,則將23補足有效位數(shù)字為23.00000000000000,然后以雙精度浮點形式存儲到d中。
<3> 將一個float型數(shù)據(jù)賦紿double變量時,數(shù)值不變,有效位數(shù)擴展到16位,在內(nèi)存中以64位(bit)存儲。將一個double型數(shù)據(jù)賦紿float變量時,截取其前面7位有效數(shù)字,存放到float變量的存儲單元(32位)中。但應(yīng)注意數(shù)值范圍不能溢出。如:
float f;
double d = 123.456789e100;
f = d;
就出現(xiàn)溢出的錯誤。
★ 為了驗證是否真的會溢出,寫如下程序試驗:
#include <stdio.h>
#include <string.h>
int main()
{
float f;
double d = 123.456789e100;
f = d;
printf("%f\n", f);
return 0;
}
在TC(Win-TC)中運行會溢出,程序會自動退出,無任何顯示( TC中欲使結(jié)果窗口停留,需在最后加一句getch(); )。而在VC中運行可以得到如下結(jié)果:
=================================================================================
12345678900000001000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000.000000
=================================================================================
分析一下,從4開始,到中間那個1共13位(此位非彼位''bit''哦),再從這個1算到最后是87位,合在一起剛好是100位,說明這個結(jié)果是正確的,并未溢出。看來數(shù)據(jù)類型在不同的編譯器中的存儲形式和表示方法還是有區(qū)別的!
<4> 字符型數(shù)據(jù)賦紿整型變量時,由于字符只占1個字節(jié),而整型變量為2個字節(jié),因此將字符數(shù)據(jù)(8位)放到整型變量的低8位中。有兩種情況:
-1- 如果所用系統(tǒng)將字符處理為無符號的量或?qū)nsigned char型變量賦值,則將字符的8位放到整型變量低8位,高8位補零。
-2- 如果所用系統(tǒng)(如Turbo C)將字符處理為帶符號的(即signed char),若字符最高位為0,則整型變量高8位補0; 若字符最高位為1,則高8位全補1。這稱為"符號擴展",這樣做的目的是使數(shù)值保持不變,如變量c以整數(shù)形式輸出為-2,將c賦紿int型變量i后i的值也是-2。
<5> 將一個int、short、long型數(shù)據(jù)賦紿一個char型變量時,只將其低8位原封不動送到char型變量(即截斷)。例如:
int i = 289;
char c = ''a'';
c = i;
★ 由于int型變量i為289,即二進制的0000000100100001,截斷賦紿c后就變成了00100001,即十進制的33,如果用"%c"輸出c, 將得到字符"!"(其ASCII碼為33)。
<6> 將帶符號的整型數(shù)據(jù)(int型)賦紿long型變量時,要進行符號擴展,將整型數(shù)的16位送到long型低16位中,如果int型數(shù)據(jù)為正值(符號位為0),則long型變量的高16位補0; 如果int型變量為負值(符號位為1),則long型變量的高16位補1,以保持數(shù)值不改變。反之,若將一個long型數(shù)據(jù)賦紿一個int型變量,只將long型數(shù)據(jù)中低16位原封不動地送到整型變量(即截斷)。例如:
int a;
long b = 8;
a = b;
★ 由于long型變量b為8,即二進制的000000000 00000000 00000000 00001000,截斷賦紿a后為00000000 00001000,a值仍為8,若long型數(shù)b超出了int型數(shù)的范圍,截斷后就與原值不等了。
<7> 將unsigned int型數(shù)據(jù)賦紿long int型變量時,不存在符號擴展問題,只需將高位補0即可。將一個unsigned類型數(shù)據(jù)賦紿一個占字節(jié)數(shù)相同的整型變量(如unsigned int -> int,unsigned long -> long,unsigned short -> short),將unsigned型變量的內(nèi)容原樣送到非unsigned型變量中,但如果數(shù)據(jù)范圍超過相應(yīng)整型的范圍,則會出現(xiàn)數(shù)據(jù)錯誤。如:
unsigned int a = 65535;
int b;
b = a;
將a整個送到b中,由于b是int型,第1位是符號位,成了負數(shù)。根據(jù)補碼知識可知,b值為-1。
★ 還是不放心,驗證一下:
#include <stdio.h>
#include <string.h>
int main()
{
unsigned int a = 65535;
int b;
b = a;
printf("%d\n", b);
return 0;
}
在TC中確實是按上述說法結(jié)果輸出為-1。而在VC中輸出的仍為65535,仔細一想,又是編譯環(huán)境的差異,在VC中,int型數(shù)據(jù)是32位的而非16位( [034] 顯示各種數(shù)據(jù)類型的長度),65535并未超出整型范圍,此時int最大可表示4294967295(232-1),所以如果想說明上述問題時在VC中應(yīng)將a賦值為4294967295,結(jié)果輸出為-1。
<8> 將非unsigned型數(shù)據(jù)賦紿長度相同的unsigned型變量,也是原樣照賦(連原有的符號位也作為數(shù)值一起傳送)。如:
#include <stdio.h>
#include <string.h>
int main()
{
unsigned int a = 65535;
int b = -1;
a = b;
printf("%u\n", a);
return 0;
}
%u是輸出無符號數(shù)時所用格式。輸出結(jié)果TC中為65535,VC中為4294967295。
以上的賦值規(guī)則看起來比較復(fù)雜,其實,不同類型的整型數(shù)據(jù)間的賦值歸根到底就是一條:按存儲單元中的存儲形式直接傳送。只要學過補碼知識的,對以上規(guī)則是不難理解的。由于C語言使用靈活,在不同類型數(shù)據(jù)之間賦值時,常常會出現(xiàn)意想不到的結(jié)果,而編譯系統(tǒng)并不提示出錯,全靠程序員的經(jīng)驗來找出問題。