<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > keil大常量計算問(wèn)題

keil大常量計算問(wèn)題

作者: 時(shí)間:2016-11-26 來(lái)源:網(wǎng)絡(luò ) 收藏
Keil C51是與ANSI C兼容的編譯器,ANSI C規范規定十進(jìn)制整數常量的默認數據類(lèi)型是int、long int和unsigned long int的其中一種,對給定的常量是其中的哪一種要看這個(gè)常量的實(shí)際大小,如果常數在-32768~32767之間則按int類(lèi)型處理,如果按int類(lèi)型處理會(huì )溢出就考慮long int或更大的數據類(lèi)型unsigned long int??傊?,編譯器總是按盡可能的原則指定常量的類(lèi)型。

但這一原則并不總能奏效,當兩個(gè)常量做運算時(shí)就可能導致溢出。如:
#define SYSCLK22118400// SYSCLK in Hz (22.1184 MHz external crystal oscillator)
#define SLIDER_REST_TIME100// in ms,slider rest time
#define REST_DELAYSYSCLK * SLIDER_REST_TIME / (65536 * 1000)
unsigned char i;
i = REST_DELAY;
keil c51中運行i為0xE1,即225,并不是期望的結果22118400 * 100 / (65536 * 1000) = 33.75,取整為33。原因分析如下:
宏替換后為:i = 22118400 * 100 / (65536 * 1000);,編譯器首先為22118400定義類(lèi)型,因為22118400不在int的表示范圍內,而在long int的范圍-2147483648~2147483647內,所以22118400按long int類(lèi)型處理,在做乘積運算時(shí)100被自動(dòng)按long int處理,22118400 * 100將按兩帶符號長(cháng)整型常量進(jìn)行運算,運算結果仍為帶符號長(cháng)整型,結果寫(xiě)成十六進(jìn)制是0x83D60000,其十進(jìn)制是-2083127296,顯然出現了溢出錯誤。keil編譯器并沒(méi)有給出任何錯誤或警告提示信息(VC++6.0還給出警告warning C4307: * : integral constant overflow),繼續進(jìn)行下一個(gè)運算65536 * 1000,結果為帶符號長(cháng)整型,十六進(jìn)制為0x3E80000,十進(jìn)制為65536000,最后按兩長(cháng)整型除法計算-2083127296 / 65536000,結果為0xFFFFFFE1,由于i為字符類(lèi)型,取0xFFFFFFE1的最低有效字節為0xE1賦值給i,i的最終值為0xE1。
解決這種溢出錯誤的方法用C語(yǔ)言的一個(gè)術(shù)語(yǔ)就是“提升”(promotion),拿上例來(lái)說(shuō)就是將22118400指定為無(wú)符號長(cháng)整型,即:
#define SYSCLK22118400UL
注:雖然只要將22118400、100、65536和1000四個(gè)常數中的一個(gè)指定為無(wú)符號長(cháng)整型即可得到正確的結果,但考慮到可讀性及規范性,應選擇大整數指定其類(lèi)型。
小結:按C51編譯器的默認類(lèi)型整數常量運算可能出現溢出錯誤,對大整數應指定其數據類(lèi)型以避免出現可能的運算錯誤。

本文引用地址:http://dyxdggzs.com/article/201611/321607.htm

轉自:幽幽靈貓

http://www.cnblogs.com/civet/archive/2011/05/31/2064959.html
/////////////
近日做射頻系統,一個(gè)簡(jiǎn)單的MCU系統,程序全部用C語(yǔ)言設計,開(kāi)發(fā)環(huán)境為盜版的Keil,用到定時(shí)器定義一個(gè)60秒的時(shí)間時(shí),如此定義:
uint16time;//16位變量

time=60*1000/TMRCYC//TMRCYC=5,定時(shí)器中斷間隔為5ms
//time總時(shí)間60s
實(shí)際運行時(shí),60s定時(shí)總是感覺(jué)不到,也就是說(shuō)60s根本就沒(méi)定義成功。
理論上講,time=12000,比16位最大值65535小,應該沒(méi)問(wèn)題,但實(shí)際就是不行,以前沒(méi)怎么用過(guò)Keil,所以也沒(méi)注意這個(gè)問(wèn)題,是否其他編譯器也有這個(gè)問(wèn)題不得而知,最后,定義改為:
time=60*1000L/TMRCYC//常量1000后加L
問(wèn)題解決。
但仍未完全明白其中道理,難道是編譯器的問(wèn)題,在此拋磚引玉,鄙人雖說(shuō)也有幾年程序經(jīng)驗,但哎,偏偏這么一個(gè)看似基礎性的東西卻不懂,希望有大蝦們解釋下,可能對你們來(lái)說(shuō)問(wèn)題很簡(jiǎn)單,但不懂或沒(méi)有遇見(jiàn)的小菜們卻是有千千萬(wàn)萬(wàn),你們就權當做好事了。
///http://bbs.21ic.com/icview-43268-1-1.html
///
上一篇下一篇共25篇

編程中無(wú)窮大常量的設定技巧2012年11月22日 13:08:05

轉自http://aikilis.tk/

如果問(wèn)題中各數據的范圍明確,那么無(wú)窮大的設定不是問(wèn)題,在不明確的情況下,很多程序員都取0x7fffffff作為無(wú)窮大,因為這是32-bit int的最大值。如果這個(gè)無(wú)窮大只用于一般的比較(比如求最小值時(shí)min變量的初值),那么0x7fffffff確實(shí)是一個(gè)完美的選擇,但是在更多的情況下,0x7fffffff并不是一個(gè)好的選擇。

  1. 很多時(shí)候我們并不只是單純拿無(wú)窮大來(lái)作比較,而是會(huì )運算后再做比較,例如在大部分最短路徑算法中都會(huì )使用的松弛操作:
    if (d[u]+w[u][v]我們知道如果u,v之間沒(méi)有邊,那么w[u][v]=INF,如果我們的INF取0x7fffffff,那么d[u]+w[u][v]會(huì )溢出而變成負數,我們的松弛操作便出錯了,更一般的說(shuō),0x7fffffff不能滿(mǎn)足“無(wú)窮大加一個(gè)有窮的數依然是無(wú)窮大”,它變成了一個(gè)很小的負數。
  2. 除了要滿(mǎn)足加上一個(gè)常數依然是無(wú)窮大之外,我們的常量還應該滿(mǎn)足“無(wú)窮大加無(wú)窮大依然是無(wú)窮大”,至少兩個(gè)無(wú)窮大相加不應該出現災難性的錯誤,這一點(diǎn)上0x7fffffff依然不能滿(mǎn)足我們。

所以我們需要一個(gè)更好的家伙來(lái)頂替0x7fffffff,最嚴謹的辦法當然是對無(wú)窮大進(jìn)行特別處理而不是找一個(gè)很大很大的常量來(lái)代替它(或者說(shuō)模擬它),但是這樣會(huì )讓我們的編程過(guò)程變得很麻煩。在我讀過(guò)的代碼中,最精巧的無(wú)窮大常量取值是0x3f3f3f3f,我不知道是誰(shuí)最先開(kāi)始使用這個(gè)精妙的常量來(lái)做無(wú)窮大,不過(guò)我的確是從一位不認識的ACMer(ID:Staginner)的博客上學(xué)到的,他/她的很多代碼中都使用了這個(gè)常量,于是我自己也嘗試了一下,發(fā)現非常好用,而當我對這個(gè)常量做更深入的分析時(shí),就發(fā)現它真的是非常精巧了。

  1. 0x3f3f3f3f的十進(jìn)制是1061109567,也就是10^9級別的(和0x7fffffff一個(gè)數量級),而一般場(chǎng)合下的數據都是小于10^9的,所以它可以作為無(wú)窮大使用而不致出現數據大于無(wú)窮大的情形。
  2. 另一方面,由于一般的數據都不會(huì )大于10^9,所以當我們把無(wú)窮大加上一個(gè)數據時(shí),它并不會(huì )溢出(這就滿(mǎn)足了“無(wú)窮大加一個(gè)有窮的數依然是無(wú)窮大”),事實(shí)上0x3f3f3f3f+0x3f3f3f3f=2122219134,這非常大但卻沒(méi)有超過(guò)32-bit int的表示范圍,所以0x3f3f3f3f還滿(mǎn)足了我們“無(wú)窮大加無(wú)窮大還是無(wú)窮大”的需求。
  3. 最后,0x3f3f3f3f還能給我們帶來(lái)一個(gè)意想不到的額外好處:如果我們想要將某個(gè)數組清零,我們通常會(huì )使用memset(a,0,sizeof(a))這樣的代碼來(lái)實(shí)現(方便而高效),但是當我們想將某個(gè)數組全部賦值為無(wú)窮大時(shí)(例如解決圖論問(wèn)題時(shí)鄰接矩陣的初始化),就不能使用memset函數而得自己寫(xiě)循環(huán)了(寫(xiě)這些不重要的代碼真的很痛苦),我們知道這是因為memset是按字節操作的,它能夠對數組清零是因為0的每個(gè)字節都是0,現在好了,如果我們將無(wú)窮大設為0x3f3f3f3f,那么奇跡就發(fā)生了,0x3f3f3f3f的每個(gè)字節都是0x3f!所以要把一段內存全部置為無(wú)窮大,我們只需要memset(a,0x3f,sizeof(a))。

所以在通常的場(chǎng)合下,0x3f3f3f3f真的是一個(gè)非常棒的選擇。




關(guān)鍵詞: keil大常量計

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>