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

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

搜索
查看: 59|回復(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覽 |閱讀模式
前言& e! p1 K' b/ S& e4 s) c4 N
直接看代碼2 r# C! F1 _8 O! g
  • 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。
    4 z3 @6 e+ }! B. z/ L* u7 O4 _: S在這里存在一個(gè)風(fēng)險(xiǎn),就是sys_time_tick_ms到達(dá)最大值后會(huì)溢出,會(huì)變成0。所以之前的代碼我的習(xí)慣是先判斷一下sys_time_tick_ms和old_time_tick的大小關(guān)系。1 S, m  P1 S! r; e1 Q* p: M
  • 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 q/ b( P8 o
  •   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\r7 X7 R# h  R; B- K
    ",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" ~, v: ]6 b/ s/ K7 V
    ",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# n" ?. R0 Z" d) L4 v
    ",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* b. e8 F9 G, @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, [  t/ I/ a2 Z5 r, X, U/ D1 \
    ",sys_time_tick_ms,data);具體打印如下  i/ |; I* v3 D' U5 X
  • 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溢出,也不影響正常功能的。
    2 V& A( O4 S1 a如果你很明白這個(gè)問題,大佬可以出門左轉(zhuǎn)了,這篇文章會(huì)浪費(fèi)你的時(shí)間的。) M, [, @8 T; l) I9 [
    無符號(hào)減法的本質(zhì), G. ]% i8 O' f+ z: I) s  s' b9 w4 e+ ?
    注意:本文只討論無符號(hào)的減法,有符號(hào)和其他數(shù)據(jù)類型本人沒有深究。8 J6 d% t, e/ f$ R: N
    在計(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
    6 }; i* {! o. Z2 J9 g3 v8 I% `",c);打印如下
    : }* e* [- B; ^$ S$ O8 dc:fffffffb這個(gè)是我們上面結(jié)論的簡單例子,將這個(gè)減法手動(dòng)模擬一下,就方便理解了5的原碼: 00000000 | 00000000 | 00000000 | 0000010110的原碼:00000000 | 00000000 | 00000000 | 000010105的補(bǔ)碼: 00000000 | 00000000 | 00000000 | 00000101! |; B! [- E3 U5 r% x0 i. ^
    -10的補(bǔ)碼:11111111 | 11111111 | 11111111 | 111101109 i% Z4 `! s6 y
    (5)補(bǔ) + (-10)補(bǔ) = 00000000  00000000  00000000  00000101 + 11111111  11111111  11111111  11110110& D2 X' d4 Q, e! W* j
    結(jié)果就是fffffffb
    0 f# y, U2 K2 x8 j( `5 ~總結(jié)
    ; S( \1 G2 S* f! v; |發(fā)現(xiàn)這個(gè)合法的操作,能更加深入的了解無符號(hào)的加法操作。但是這種操作還是要慎重,我的測試環(huán)境是IAR7.2,建議大家使用時(shí)先測試一下,還是要謹(jǐn)慎的,別因?yàn)檫@個(gè)問題"捅了婁子"。6 H8 ?% {" D! n: d5 @8 L
    除了需要在開發(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)境下是否有問題
    4 F0 x0 s2 \8 m+ f( P8 m* n5 `& R! ~2、養(yǎng)成良好習(xí)慣,寫清楚注釋
    / i& Q' W( c" e. D6 XEND
    ; ^* X1 z5 Z4 @  W- k' W1 W ' u0 ~2 r( ^) o& t" h
    . r3 }  C/ a& D* D# \
    ?如何查找官方資料
      n- ?* k1 }( @6 i$ p4 M?VS code調(diào)試C代碼  必讀$ k( Y& a( z$ F) W6 E& H
    ?STM32中volatile的應(yīng)用
    * p0 ?- p$ u4 ^' X# G' r7 Q?回調(diào)函數(shù)在STM32中的應(yīng)用   必讀$ W2 h4 J" @2 h* k6 ~1 ]) {9 ~
    ?設(shè)計(jì)一款兼容ST207和GD207的開發(fā)板
  • 發(fā)表回復(fù)

    本版積分規(guī)則


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