<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 單片機C語言中define的妙用

          單片機C語言中define的妙用

          作者: 時間:2016-11-29 來源:網(wǎng)絡(luò) 收藏
          單片機C語言define的妙用

          最近一款產(chǎn)品調(diào)試時發(fā)現(xiàn)了問題,在一起檢查一個小伙伴的C程序。問題不大,但暴露了一點問題。
          比如:PORTB=0x23; //他的意思是把第5和第2位置1
          可是你能一下子看出來第5和第2位置1嗎?其實應(yīng)該是0x24,他并沒有發(fā)現(xiàn)這個錯誤,算錯了,所以正確的是:
          PORTB=0x23;
          其實,我們完全可以避免這個錯誤。
          打開我們編譯器自帶的頭文件,比如AVR Tiny13頭文件中有如下語句:
          # define PB5 5
          # define PB4 4
          # define PB3 3
          # define PB2 2
          # define PB1 1
          # define PB0 0

          看似沒什么用,其實大有用處。
          PORTB=0x24;就可以寫為:
          PORTB=(1<這樣,是不是一下子就能看清誰跟誰了?也方便別人閱讀。

          define的妙用遠(yuǎn)不止此,但基本的用法簡單,要靈活運用,才行。
          下面是摘抄自網(wǎng)上的define用法,希望你能掌握并運用。


          #define用法
          1.簡單的define定義

          #define MAXTIME 1000

          一個簡單的MAXTIME就定義好了,它代表1000,如果在程序里面寫

          if(i

          編譯器在處理這個代碼之前會對MAXTIME進行處理替換為1000。

          這樣的定義看起來類似于普通的常量定義CONST,但也有著不同,因為define的定義更像是簡單的文本替換,而不是作為一個量來使用,這個問題在下面反映的尤為突出。

          2.define的“函數(shù)定義”
          define可以像函數(shù)那樣接受一些參數(shù),如下

          #define max(x,y) (x)>(y)?(x):(y);

          這個定義就將返回兩個數(shù)中較大的那個,看到了嗎?因為這個“函數(shù)”沒有類型檢查,就好像一個函數(shù)模板似的,當(dāng)然,它絕對沒有模板那么安全就是了。可以作為一個簡單的模板來使用而已。

          但是這樣做的話存在隱患,例子如下:
          #define Add(a,b) a+b;
          在一般使用的時候是沒有問題的,但是如果遇到如:c * Add(a,b) * d的時候就會出現(xiàn)問題,代數(shù)式的本意是a+b然后去和c,d相乘,但是因為使用了define(它只是一個簡單的替換),所以式子實際上變成了
          c*a + b*d

          另外舉一個例子:
          #define pin (int*);
          pin a,b;
          本意是a和b都是int型指針,但是實際上變成int* a,b;
          a是int型指針,而b是int型變量。
          這是應(yīng)該使用typedef來代替define,這樣a和b就都是int型指針了。

          所以我們在定義的時候,養(yǎng)成一個良好的習(xí)慣,建議所有的層次都要加括號。

          3.宏的單行定義

          #define A(x) T_##x
          #define B(x) #@x

          #define C(x) #x
          我們假設(shè):x=1,則有:
          A(1)------〉T_1
          B(1)------〉1
          C(1)------〉"1"

          (這里參考了 hustli的文章)

          4.define的多行定義

          define可以替代多行的代碼,例如MFC中的宏定義(非常的經(jīng)典,雖然讓人看了惡心)

          #define MACRO(arg1, arg2) do { /
          /
          stmt1; /
          stmt2; /
          /
          } while(0)
          關(guān)鍵是要在每一個換行的時候加上一個"/"


          5.在大規(guī)模的開發(fā)過程中,特別是跨平臺和系統(tǒng)的軟件里,define 最重要的功能是條件編譯。

          就是:
          #ifdef WINDOWS
          ......
          ......
          #endif
          #ifdef LINUX
          ......
          ......
          #endif

          可以在編譯的時候通過#define設(shè)置編譯環(huán)境

          6.如何定義宏、取消宏

          //定義宏
          #define [MacroName] [MacroValue]
          //取消宏
          #undef [MacroName]
          普通宏
          #define PI (3.1415926)

          帶參數(shù)的宏
          #define max(a,b) ((a)>(b)? (a),(b))
          關(guān)鍵是十分容易產(chǎn)生錯誤,包括機器和人理解上的差異等等。

          7.條件編譯

          #ifdef XXX…(#else)…#endif
          例如 #ifdef DV22_AUX_INPUT
          #define AUX_MODE 3
          #else
          #define AUY_MODE 3
          #endif
          #ifndef XXX …(#else) …#endif

          8.頭文件(.h)可以被頭文件或C文件包含

          重復(fù)包含(重復(fù)定義)
          由于頭文件包含可以嵌套,那么C文件就有可能包含多次同一個頭文件,就可能出現(xiàn)重復(fù)定義的問題的。
          通過條件編譯開關(guān)來避免重復(fù)包含(重復(fù)定義)
          例如
          #ifndef __headerfileXXX__
          #define __headerfileXXX__

          文件內(nèi)容

          #endif
          9. #define中的#、## && #@

          前些一段時間在看WinCE的Code時發(fā)現(xiàn)在宏定義中有用到##,如下所示

          #define GPEBLT_FUNCNAME(basename) (SCODE (GPE::*)(struct GPEBltParms*))&GPE::##basename

          在#define中,標(biāo)準(zhǔn)只定義了#和##兩種操作。#用來把參數(shù)轉(zhuǎn)換成字符串,##則用來連接兩個前后兩個參數(shù),把它們變成一個字符串。

          1#define ToString(a) #a

          2ToString( A b Cd ); //A b Cd

          3ToString( A/n b Cd ); //A

          4 // b Cd

          5ToString( A/ n b Cd ); //A n b Cd

          6

          7

          8#define ConCat(x, y) x ## y

          9ConCat( "ABC", "DEF" );

          10ConCat( 123, 4);

          11ConCat( 123.0, 5);

          12//=================================

          13// Cat( 123.0, 5.5);

          14// Cat( a, b );

          15// Cat( "ABC", d );

          16// Cat( a, 1234 );

          17// Cat( "ABC", 1234 );

          18//===== above cant compile =======

          19

          20

          另外,在網(wǎng)上搜到還有一種用法:#@,把參數(shù)轉(zhuǎn)換成字符



          1#define ToChar(a) #@a

          2ToChar(a); // a

          3ToChar(ab); // b

          4ToChar(abc); // c

          5ToChar(abcd); // d

          6//ToChar(abcde); // too many characters in constant

          7ToChar(1.); // .

          這個沒在標(biāo)準(zhǔn)上看到。上述測試是在VS studio環(huán)境下做的。不知道GCC中是否有同樣的用法。



          最后附上#define和typedef的區(qū)別

          1) #define是預(yù)處理指令,在編譯預(yù)處理時進行簡單的替換,不作正確性檢查,不關(guān)含義是否正確照樣帶入,只有在編譯已被展開的源程序時才會發(fā)現(xiàn)可能的錯誤并報錯。例如:
          #define PI 3.1415926
          程序中的:area=PI*r*r 會替換為3.1415926*r*r
          如果你把#define語句中的數(shù)字9寫成字母g 預(yù)處理也照樣帶入。

          2)typedef是在編譯時處理的。它在自己的作用域內(nèi)給一個已經(jīng)存在的類型一個別名,但是You cannot use the typedef specifier inside a functiondefinition。

          3)typedef int * int_ptr;

          #define int_ptr int *
          作用都是用int_ptr代表 int* ,但是二者不同,正如前面所說,#define在預(yù)處理時進行簡單的替換,而typedef不是簡單替換,而是采用如同定義變量的方法那樣來聲明一種類型。也就是說;

          //refer to (xzgyb(老達摩))
          #define int_ptr int *
          int_ptr a, b; //相當(dāng)于int * a, b; 只是簡單的宏替換

          typedef int* int_ptr;
          int_ptr a, b; //a, b 都為指向int的指針,typedef為int* 引入了一個新的助記符


          這也說明了為什么下面觀點成立
          //QunKangLi(維護成本與程序員的創(chuàng)造力的平方成正比)
          typedef int * pint ;
          #define PINT int *

          那么:
          const pint p ;//p不可更改,但p指向的內(nèi)容可更改
          const PINT p ;//p可更改,但是p指向的內(nèi)容不可更改。

          pint是一種指針類型 const pint p 就是把指針給鎖住了p不可更改
          而const PINT p 是constint * p 鎖的是指針p所指的對象。

          4)還應(yīng)經(jīng)注意到#define 不是語句不要在行末加分號,否則會連分號一塊置換。


          關(guān)鍵詞: 單片機C語言defin

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();