第19節(jié):加法運(yùn)算中,神秘中間變量的類(lèi)型
在開(kāi)始本節(jié)內(nèi)容之前,先告訴大家前面第十一節(jié)內(nèi)容有一處筆誤,unsigned long的數(shù)據(jù)長(zhǎng)度應(yīng)該是4個(gè)字節(jié),而不是3個(gè)字節(jié)。
本文引用地址:http://m.butianyuan.cn/article/201611/319829.htm上一節(jié)提到了一個(gè)“隱藏中間變量”的概念,兩個(gè)加數(shù)相加,其結(jié)果先保存在一個(gè)“隱藏中間變量”里,然后再把這個(gè)“隱藏中間變量”賦值給左邊的“保存變量”。這里的“隱藏中間變量”到底是unsigned int類(lèi)型還是unsigned long類(lèi)型?為了研究它的規(guī)律,在keil自帶的C51編譯環(huán)境下,我專(zhuān)門(mén)編寫(xiě)了好幾個(gè)測(cè)試程序來(lái)觀察實(shí)際運(yùn)行的結(jié)果。
“保存變量”=“加數(shù)1”+“加數(shù)2”;
我測(cè)試的程序如下:
(1)“保存變量”為 unsigned int類(lèi)型,“加數(shù)1”為unsigned char類(lèi)型,“加數(shù)2”為unsigned char 類(lèi)型。
unsigned int a;
unsigned char x=0x12;
unsigned char y=0xfe;
a=x+y;
運(yùn)行結(jié)果:a等于0x0110。
分析過(guò)程:兩個(gè)char類(lèi)型的數(shù)相加,當(dāng)運(yùn)算結(jié)果大于char本身時(shí),并沒(méi)有發(fā)生溢出現(xiàn)象,int型的“保存變量”a最終得到了完整的結(jié)果。
初步結(jié)論:這種情況,“隱藏中間變量”應(yīng)該為unsigned int 類(lèi)型。
(2)“保存變量”為 unsigned long類(lèi)型,“加數(shù)1”為unsigned int類(lèi)型,“加數(shù)2”為unsigned char 類(lèi)型。
unsigned long a;
unsigned int x=0xfffe;
unsigned char y=0x12;
a=x+y;
運(yùn)行結(jié)果:a等于十六進(jìn)制的0x0010。
分析過(guò)程:一個(gè)int類(lèi)型的數(shù)與一個(gè)char類(lèi)型的數(shù)相加,當(dāng)運(yùn)算結(jié)果大于其中最大加數(shù)int類(lèi)型本身時(shí),本來(lái)以為運(yùn)算結(jié)果應(yīng)該是long類(lèi)型的0x00010010,結(jié)果是int類(lèi)型的0x0010,發(fā)生了溢出現(xiàn)象。
初步結(jié)論:這種情況,“隱藏中間變量”應(yīng)該為unsigned int 類(lèi)型。
(3)“保存變量”為 unsigned long類(lèi)型,“加數(shù)1”與“加數(shù)2”都為常量。
unsigned long a;
a=50000+50000;
運(yùn)行結(jié)果:a等于100000。
分析過(guò)程:int的最大數(shù)據(jù)范圍是65535,而兩個(gè)常量相加,其結(jié)果超過(guò)了65535還能完整保存下來(lái)。
初步結(jié)論:這種情況,“隱藏中間變量”等于左邊的“保存變量”類(lèi)型。
(4)“保存變量”為 unsigned long類(lèi)型,“加數(shù)1”為unsigned int類(lèi)型,“加數(shù)2”為常量。
unsigned long a;
unsigned long b;
unsigned int x=50000;
a=x+30000;
b=x+50000;
運(yùn)行結(jié)果:a等于14464,b等于100000。
分析過(guò)程:本來(lái)以為a應(yīng)該等于80000的,結(jié)果是14464發(fā)生了溢出。而b是100000沒(méi)有發(fā)生溢出。
初步結(jié)論:這是一種很怪異的現(xiàn)象,為什么同樣的類(lèi)型,因?yàn)槌A康牟煌?,一個(gè)發(fā)生了溢出,另外一個(gè)沒(méi)有發(fā)生溢出?這時(shí)的“隱藏中間變量”到底是int類(lèi)型還是long類(lèi)型我無(wú)法下結(jié)論。
經(jīng)過(guò)上述簡(jiǎn)單的測(cè)試,我發(fā)現(xiàn)規(guī)律是模糊的,模糊的規(guī)律就不能成為規(guī)律。如果真要按這種思路研究下去,那真是沒(méi)完沒(méi)了,因?yàn)檫€有很多情況要研究,當(dāng)超過(guò)3個(gè)以上加數(shù)相加,同時(shí)存在long,int,char,常量這4種類(lèi)型時(shí)又是什么規(guī)律?在不同的C編譯器里又會(huì)是什么現(xiàn)象?即使把所有情況的規(guī)律摸清楚了又能怎么樣,因?yàn)槟敲捶彪s很容易忘記導(dǎo)致出錯(cuò)。有什么解決的辦法嗎?現(xiàn)在跟大家分享一種很簡(jiǎn)單的解決辦法。
當(dāng)遇到有爭(zhēng)議的問(wèn)題時(shí),還有一種解決思路是:與其參與爭(zhēng)議越陷越深,還不如想辦法及時(shí)抽身繞開(kāi)爭(zhēng)議。在上述運(yùn)算中,只要經(jīng)過(guò)簡(jiǎn)單的變換,讓它們遵循“所有參與運(yùn)算的變量,左邊的變量類(lèi)型必須跟右邊的保存變量類(lèi)型一致”這個(gè)原則,那么就不會(huì)存在這些爭(zhēng)議了。
(5)比如上述第(4)個(gè)例子,其轉(zhuǎn)換方法如下:
unsigned long a;
unsigned long b;
unsigned int x=50000;
Unsigned long t; //多增加一個(gè)long類(lèi)型的變量,用來(lái)變換類(lèi)型
t=0; //把變量的高位和低位全部清零。
t=x; //把x的數(shù)值先放到一個(gè)long類(lèi)型的變量里,讓”加數(shù)”跟”保存變量”類(lèi)型一致。
a=t+30000;
b=t+50000;
運(yùn)行結(jié)果:a等于80000,b等于100000。都沒(méi)有發(fā)生溢出。
(6)比如上述第(2)個(gè)例子,其轉(zhuǎn)換方法如下:
unsigned long a;
unsigned int x=0xfffe;
unsigned char y=0x12;
unsigned long t; //多增加一個(gè)long類(lèi)型的變量,用來(lái)變換類(lèi)型。
unsigned long r; //多增加一個(gè)long類(lèi)型的變量,用來(lái)變換類(lèi)型。
t=0;//把變量的高位和低位全部清零。
t=x; //把x的數(shù)值先放到一個(gè)long類(lèi)型的變量里,讓”加數(shù)”跟”保存變量”類(lèi)型一致。
r=0; //把變量的高位和低位全部清零。
r=y //把y的數(shù)值先放到一個(gè)long類(lèi)型的變量里,讓”加數(shù)”跟”保存變量”類(lèi)型一致。
a=t+r;
運(yùn)行結(jié)果:a等于十六進(jìn)制的0x00010010,沒(méi)有發(fā)生溢出現(xiàn)象。
下節(jié)預(yù)告:減法運(yùn)算的常見(jiàn)格式。
評(píng)論