電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 58|回復(fù): 0
收起左側(cè)

聊聊數(shù)據(jù)溢出的事

[復(fù)制鏈接]

485

主題

485

帖子

1623

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
1623
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2022-6-27 08:30:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
前言) o: A2 G5 {- G. ?# ]  j3 D! W
直接看代碼) A5 X  i7 A. @9 x. t
  • uint32_t Time_Interval(){  static uint32_t old_time_tick;  uint32_t data;  data = sys_time_tick_ms - old_time_tick;  old_time_tick = sys_time_tick_ms;  return data;}上述代碼,sys_time_tick_ms每隔1ms自動(dòng)加1,Time_Interval函數(shù)的作用是的,計(jì)算上一次調(diào)用Time_Interval和下一次調(diào)用的時(shí)間差,單位ms。
    ) E3 `. U/ R& W3 M, j+ d在這里存在一個(gè)風(fēng)險(xiǎn),就是sys_time_tick_ms到達(dá)最大值后會(huì)溢出,會(huì)變成0。所以之前的代碼我的習(xí)慣是先判斷一下sys_time_tick_ms和old_time_tick的大小關(guān)系。
    0 H8 R4 j6 I* Y; r- k
  • uint32_t Time_Interval(){  static uint32_t old_time_tick;  uint32_t data;  if(sys_time_tick_ms > old_time_tick)    data = sys_time_tick_ms - old_time_tick;  else    data = sys_time_tick_ms + (0xFFFFFFFF - old_time_tick);  old_time_tick = sys_time_tick_ms;  return data;}然而一次和同事交流的時(shí)候,我意識(shí)到其實(shí)不用這么做的,sys_time_tick_ms直接減去old_time_tick就行。如下代碼# U7 ?9 J  h. s1 z+ Q7 K: g) n
  •   sys_time_tick_ms = 0xFFFFFFFF - 2;  old_time_tick = sys_time_tick_ms;  sys_time_tick_ms++;  data = sys_time_tick_ms-old_time_tick;  printf("sys_time_tick_ms:%x  data:%d\r
    8 `6 b, @) D0 ], u",sys_time_tick_ms,data);  sys_time_tick_ms++;  data = sys_time_tick_ms-old_time_tick;  printf("sys_time_tick_ms:%x  data:%d\r4 A. j( P- P; c2 A9 T5 `9 u! b
    ",sys_time_tick_ms,data);  sys_time_tick_ms++;  data = sys_time_tick_ms-old_time_tick;  printf("sys_time_tick_ms:%x  data:%d\r1 ]: g9 h" R; H9 ?1 Y6 I; O
    ",sys_time_tick_ms,data);  sys_time_tick_ms++;  data = sys_time_tick_ms-old_time_tick;  printf("sys_time_tick_ms:%x  data:%d\r) {$ H% `7 O: ~4 F
    ",sys_time_tick_ms,data);  sys_time_tick_ms++;  data = sys_time_tick_ms-old_time_tick;  printf("sys_time_tick_ms:%x  data:%d\r
    0 S+ J1 F0 \5 t  w9 Z3 }8 u",sys_time_tick_ms,data);具體打印如下
    6 h) g6 Y- g1 C. b% i$ Y& z
  • sys_time_tick_ms:fffffffe  data:1sys_time_tick_ms:ffffffff  data:2sys_time_tick_ms:0  data:3sys_time_tick_ms:1  data:4sys_time_tick_ms:2  data:5可以看出,這種情況下,即使sys_time_tick_ms溢出,也不影響正常功能的。
    4 b; u. R* u5 t8 J' L. ]如果你很明白這個(gè)問題,大佬可以出門左轉(zhuǎn)了,這篇文章會(huì)浪費(fèi)你的時(shí)間的。; E# F0 v1 H6 G5 h
    無符號(hào)減法的本質(zhì)
    , y5 i$ ^# }, u$ W0 Z注意:本文只討論無符號(hào)的減法,有符號(hào)和其他數(shù)據(jù)類型本人沒有深究。' h! F, ]2 X$ g5 a# G+ d
    在計(jì)算機(jī)中,無符號(hào)的減法運(yùn)算是通過補(bǔ)碼來進(jìn)行的,比如a-b,實(shí)質(zhì)上是a補(bǔ) + (-b補(bǔ))。補(bǔ)碼的定義不懂的同學(xué)請(qǐng)自行百度。
  • uint32_t a,b,c;a=5;b=10;c=a-b;printf("c:%x\r
    5 U5 S+ G& b% d, z  r* U",c);打印如下
    6 O4 b/ k+ @0 ^) g1 C  Yc:fffffffb這個(gè)是我們上面結(jié)論的簡單例子,將這個(gè)減法手動(dòng)模擬一下,就方便理解了5的原碼: 00000000 | 00000000 | 00000000 | 0000010110的原碼:00000000 | 00000000 | 00000000 | 000010105的補(bǔ)碼: 00000000 | 00000000 | 00000000 | 00000101- b5 k+ m5 y* c( W' i
    -10的補(bǔ)碼:11111111 | 11111111 | 11111111 | 111101108 ^3 L) Y% Q) d8 k2 h
    (5)補(bǔ) + (-10)補(bǔ) = 00000000  00000000  00000000  00000101 + 11111111  11111111  11111111  11110110
    1 J1 }0 D# N$ [結(jié)果就是fffffffb
    8 r4 Y8 a) j$ Y6 W& K總結(jié)
    # E# {1 Q6 g; Z發(fā)現(xiàn)這個(gè)合法的操作,能更加深入的了解無符號(hào)的加法操作。但是這種操作還是要慎重,我的測試環(huán)境是IAR7.2,建議大家使用時(shí)先測試一下,還是要謹(jǐn)慎的,別因?yàn)檫@個(gè)問題"捅了婁子"。) Y% B8 N) C6 s( n! M$ P
    除了需要在開發(fā)環(huán)境中測試一下外,還需要額外的備注如下?
  • uint32_t Time_Interval(){  static uint32_t old_time_tick;  uint32_t data;  data = sys_time_tick_ms - old_time_tick;//數(shù)據(jù)溢出后,由于無符號(hào)減法特性,也不會(huì)出問題  old_time_tick = sys_time_tick_ms;  return data;}建議加上這樣的注釋,方便其他人維護(hù),代碼清晰易讀。就像switch語句,合并處理某些情況是,最好添加備注。
  • switch (data){  case:0  case:1//0和1情況一樣,合并處理    /*do some thing*/    break;  case:2    /*do some thing*/    break;  default:    break;}總結(jié)兩點(diǎn):1、測試對(duì)應(yīng)開發(fā)環(huán)境下是否有問題
      ?! X& E$ \) M! n# A2、養(yǎng)成良好習(xí)慣,寫清楚注釋8 H/ ]2 h2 V+ E0 X! k) q
    END" C6 g3 C  r  M! J; x; C

    0 L$ i: |1 o! D$ U: F0 o7 x3 ^
    7 x( M5 i, k$ J. x/ H! Q" c  M?如何查找官方資料  P+ W6 J0 S% D5 T& o
    ?VS code調(diào)試C代碼  必讀  a" j1 B- }8 Y0 a$ l$ z
    ?STM32中volatile的應(yīng)用
    , t  i. O& F9 r; t; U/ j?回調(diào)函數(shù)在STM32中的應(yīng)用   必讀* B( p1 V7 F6 J- @. U
    ?設(shè)計(jì)一款兼容ST207和GD207的開發(fā)板
  • 發(fā)表回復(fù)

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表