C 兩個無符號數相減的問題

2022-05-04 15:42:06 字數 2522 閱讀 5532

因為乙個裸機軟定時器的溢位問題,

static uint32_t _timer_ticks = 0

;void

timer_ticks()

void

soft_timer_loop()

else

target->timeout_cb();}}

}

為了解決這個bug,有人可以把判斷條件換成

if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0

)

這個涉及到2個無符號數相減的問題。

微機原理中計算通過alu計算,加減的時候,alu不認識什麼符號。他有兩個輸入端a,b。 a端直接輸入,b端的看情況,如果是+則直接輸入,如果是-則經過乙個反向器並加1輸入。 他只管計算,並把結果反回給程式,至於這個結果是什麼型別,就由程式來處理了

簡單一句,無符號數的加減法等同於補碼進行加減法,只是最後對於結果的解釋不一樣,無符號數a-b,可以和補碼表示的有符號數一樣,轉化成,a+(b的補碼),即a+(~b+1 )

這裡假設_timer_ticks和 target->timeout都是8位的。target->repeat +_timer_ticks 溢位了。1ms計數的情況下,按實際 target->timeout是要比4294967295(49.7天)要小的多的乙個數。

這裡按8位數寫

假設_timer_ticks = 250 ,target->repeat = 10 則 target->timeout = 4 

則target->timeout -_timer_ticks  

_timer_ticks 原碼 1111 1010

補碼 0000 0110

target->timeout + 0000 0110 = 10強制轉換為int 也是大於0的。

_timer_ticks = 251 ((uint8_t)(target->timeout -_timer_ticks)) = 0x09轉為有符號 (char)((uint8_t)(target->timeout -_timer_ticks)) = 9

。。。_timer_ticks = 255 ((uint8_t)(target->timeout -_timer_ticks)) =0x05轉為有符號(char)((uint8_t)(target->timeout -_timer_ticks)) = 5

。。。_timer_ticks = 3  ((uint8_t)(target->timeout -_timer_ticks)) = 0x01轉為有符號(char)((uint8_t)(target->timeout -_timer_ticks)) = 1

_timer_ticks = 4  ((uint8_t)(target->timeout -_timer_ticks)) = 0x00轉為有符號(char)((uint8_t)(target->timeout -_timer_ticks)) = 0

_timer_ticks = 5  ((uint8_t)(target->timeout -_timer_ticks)) = 0xff轉為有符號(char)((uint8_t)(target->timeout -_timer_ticks)) < -1

所以解決了溢位的的時候,因為target->timeout 必定比_timer_ticks小,而立即執行的bug。

那麼這麼些有bug嗎?首先沒有溢位的情況下,很好理解,這時候其實不用考慮什麼補碼,不用再繞一層,按常識走。

就是溢位的情況下,有,假設在_timer_ticks = 128的時候  target->repeat = 128 ,這是target->timeout = 1

_timer_ticks = 129  (int)((uint32_t)(target->timeout -_timer_ticks)) = -128 這tm就成立了啊。

或者說_timer_ticks = 128的時候  target->repeat = 129 這是target->timeout = 2

_timer_ticks = 129  (int)((uint32_t)(target->timeout -_timer_ticks)) = -129 這tm就成立了啊。

_timer_ticks = 130  (int)((uint32_t)(target->timeout -_timer_ticks)) = -128 這tm就成立了啊。

這裡再極限一些 target->repeat = 250,當_timer_ticks = 6的時候,target->timeout = 1

_timer_ticks = 2  (int)((uint32_t)(target->timeout -_timer_ticks)) = -1 這tm就成立了啊。

這裡只要target->repeat <= 127(uint8_max/2) 就不會出現這種bug,而uint32的一半要20多天,所以這個bug,注意一下就行,平時不會出現。

還有一種方法,就是_timer_ticks target->timeout定義為64位的 那樣溢位需要1億年,根本不會溢位了。

有符號數和無符號數的轉換問題

最近做了乙個專案,需要高八位和低八位的資料顛倒一下,需要轉換的資料是有符號的16位資料,我編寫的函式如下 16bit資料高低位互換程式 int16 rearrange16 int16 data 後來發現乙個問題 送出來的資料都沒有負數,正常情況下是正負都有的,經過除錯發現了問題所在,現在把我的心 得...

C語言中無符號數和有符號數相加問題

32位的int的最大值與最小值,最大值2的31次方 1 pow 2,31 1,最小值為負的2的31次方 pow 2,31 c語言中沒有次冪的運算子,是異或的運算子。看個題 include int main 結果是 14 6 意想不到吧?為什麼結果這樣呢?原來有符號數和無符號數進行比較運算時 有符號數...

C語言中的有符號數與無符號數

1.c語言支援所有整型資料型別的有符號和無符號運算,儘管c語言標準並沒有指定用哪種方式來表示有符號整數,但是幾乎所有的 機器都使用補碼。2.c 語言中預設的整形資料是有符號的,並且允許無符號數和有符號數之間進行轉換。轉換的原則是底層的位保持不變。3.執行運算時,如果乙個運算數是有符號的而另乙個是無符...