c語言學習--巨集定義、條件編譯等
1. 防止一個頭檔案被重複包含
- #ifndef COMDEF_H
- #define COMDEF_H
- //標頭檔案內容
- #endif
- typedef unsigned char boolean; /* Boolean value type. */
- typedef unsigned longint uint32; /* Unsigned 32 bit value */
-
typedef unsigned short
- typedef unsigned char uint8; /* Unsigned 8 bit value */
- typedefsignedlongint int32; /* Signed 32 bit value */
- typedefsignedshort int16; /* Signed 16 bit value */
- typedefsignedchar int8; /* Signed 8 bit value */
- #define MEM_B( x ) ( *( (int8 *) (x) ) )
- #define MEM_W( x ) ( *( (uint16 *) (x) ) )
會存在Duplication of Side Effects問題。這裡的Side Effect是指巨集在展開的時候對其引數可能進行多次Evaluation(也就是取值),但是如果這個巨集引數是一個函式,那麼就有可能被呼叫多次從而達到不一致的結果,甚至會發生更嚴重的錯誤。比如:
-
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
- #define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
- c = min(a,foo(b));
- #define min(X,Y) ({\
- typeof (X) x_ = (X);\
- typeof (Y) y_ = (Y);\
- (x_ < y_) ? x_ : y_; })
5,得到一個field在結構體(struct)中的偏移量
- #define FPOS( type, field ) ( (dword) &(( type *) 0)-> field )
6,得到一個結構體中field所佔用的位元組數
- #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
7,按照LSB格式把兩個位元組轉化為一個Word
- #define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
8,按照LSB格式把一個Word轉化為兩個位元組
- #define<span style="white-space:pre"> </span>FLOPW( ray, val ) \
- <span style="white-space:pre"> </span>(ray)[0] = ((val) / 256); \
- <span style="white-space:pre"> </span>(ray)[1] = ((val) & 0xFF)
9,得到一個變數的地址(word寬度)
- #define B_PTR( var ) ( (int8 *) (void *) &(var) )
- #define W_PTR( var ) ( (uint16 *) (void *) &(var) )
10,得到一個字的高位和低位位元組
- #define WORD_LO(xxx) ((byte) ((uint16)(xxx) & 255))
- #define WORD_HI(xxx) ((byte) ((uint16)(xxx) >> 8))
11,返回一個比X大的最接近的8的倍數
- #define RND8( x ) ((((x) + 7) / 8 ) * 8 )
12,將一個字母轉換為大寫
- #define UPCASE( c ) ( ((c) >= ''a'' && (c) <= ''z'') ? ((c) - 0x20) : (c) )
13,判斷字元是不是10進值的數字
- #define DECCHK( c ) ((c) >= ''0'' && (c) <= ''9'')
14,判斷字元是不是16進值的數字
- #define HEXCHK( c ) ( ((c) >= ''0'' && (c) <= ''9'') ||\
- ((c) >= ''A'' && (c) <= ''F'') ||\
- ((c) >= ''a'' && (c) <= ''f'') )
15,防止溢位的一個方法
- #define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
16,返回陣列元素的個數
- #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
17,返回一個無符號數n尾的值
MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
- #define MOD_BY_POWER_OF_TWO( val, mod_by ) \
- ( (dword)(val) & (dword)((mod_by)-1) )
18,對於IO空間對映在儲存空間的結構,輸入輸出處理
- #define inp(port) (*((volatile byte *) (port)))
- #define inpw(port) (*((volatile word *) (port)))
- #define inpdw(port) (*((volatile dword *)(port)))
- #define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))
- #define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
- #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
ANSI標準說明了五個預定義的巨集名。它們是:
_LINE_
_FILE_
_DATE_
_TIME_
_STDC_
如果編譯不是標準的,則可能僅支援以上巨集名中的幾個,或根本不支援。記住編譯程式也許還提供其它預定義的巨集名。
_LINE_標識當前程式碼所在的行號
_FILE_標識程式碼所在的檔名
_DATE_巨集指令含有形式為月/日/年的串,表示原始檔被翻譯到程式碼時的日期。
原始碼翻譯到目的碼的時間作為串包含在_TIME_中。串形式為時:分:秒。
如果實現是標準的,則巨集_STDC_含有十進位制常量1。如果它含有任何其它數,則實現是非標準的。
可以定義巨集,例如:
當定義了_DEBUG,輸出資料資訊和所在檔案所在行
- #ifdef _DEBUG
- #define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
- #else
- #define DEBUGMSG(msg,date)
- #endif
20. 巨集定義防止使用是錯誤用小括號包含。
例如:
- #define ADD(a,b) (a+b)
例如:
- #difne DO(a,b) a+b; a++;
- if(...)
- DO(a,b); //產生錯誤
- else
- ...
- #define DO(a,b) do{a+b;a++;}while(0)
21. 巨集中"#"和"##"的用法
#的功能是將其後面的巨集引數進行字串化操作(Stringfication)。
##被稱為連線符(concatenator),用來將兩個Token連線為一個Token。注意這裡連線的物件是Token就行,而不一定是巨集的變數。
用法:
-
相關推薦
c語言學習--巨集定義、條件編譯等
1. 防止一個頭檔案被重複包含 #ifndef COMDEF_H #define COMDEF_H //標頭檔案內容 #endif 2. 重新定義一些型別,防止由於各種平臺和編譯器的不同,而產生的型別位元組數差異,方便移
C語言詳解(6)巨集定義和條件編譯
巨集定義和條件編譯 一、概述 巨集定義是C語言的預處理功能。巨集定義就是簡單的替換,不作為計算,不也作為表示式。在C語言中作為預處理指令包括:巨集定義、檔案包含、條件編譯。 條件編譯其實就是將if…else…的設計思想引入到預處理功能中,給編譯器使用的。條件編譯時通過
C語言開關巨集定義的學習##__VA_ARGS__
最近寫c程式,學到一種開關巨集,極大提高程式的控制性: #define __DEBUG #ifdef __DEBUG #define tnfs_print(format, ...) printf (format, ##__VA_ARGS__) #else #define tnfs_print
C語言(二 運算子、條件語句、指標)
C運算子 包括算數運算子,邏輯運算子,關係運算符,位運算子,賦值運算子,其他運算子。 算術運算子 就是加減乘除求餘,自增自減等算術。 邏輯運算子 與:&&,或:||,非:! 關係運算符 等於,大於,小於等組合 位運算子 位與:&,位或:|,位左移<<,位右
【C語言】巨集定義define 和型別重新命名typedef
C語言裡面有兩個不容易區分的語法概念,巨集定義define 和型別重新命名typedef。下面我們來談一下兩者之間的差異。 1.型別重新命名typedef: 關鍵字typedef提供了一種為已定義好的資料型別建立別名的機制,為了建立更簡短的型別名,通常使用type
C語言中巨集定義和函式的取捨
原文連結:http://www.embedu.org/Column/Column177.htm 要寫好C語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。 在軟體開發過程中,經常有一些常用或者通用的功能或者程式碼段,這些功能既可以寫成函式,也可以
C語言應用巨集定義解決三角形的面積問題
#include <stdio.h> #include<math.h> #define s(a,b,c) ((0.5)*((a)+(b)+(c))) #define area(s,a,b,c) sqrt((s)*((s)-(a))*((s
C語言的預處理之"條件編譯"
C語言的預處理主要有三個方面的內容: 巨集定義 檔案包含 條件編譯 預處理命令以符號"#"開頭。 採用條件編譯,可以減少被編譯的語句,從而減少目標的長度。當條件編譯段比較多時,目標程式長度可以大大減少。 條件編譯主要包括: #if
玩兒轉C語言:巨集定義(1)
1、為什麼要有巨集定義? 程式碼中某個特定數值需要參與運算,而且該數值作用於多個地方,當需要對該數值進行修改時,希望只改動一個地方就能實現該數值的全部更新;即便某個數值只用到一次,當修改時也會面臨搜尋閱讀大量程式碼、數值含義不明晰的問題;某些“操作塊”封裝成
Makefile中用巨集定義進行條件編譯(gcc -D)/在Makefile中進行巨集定義-D
在原始碼裡面如果這樣是定義的: #ifdef MACRONAME //可選程式碼 #endif 那在makefile裡面 gcc -D MACRONAME=MACRODEF 或者 gcc -D MACRONAME 這樣就定義了預處理巨集,編譯的時候可選程式碼就會被編譯進去了。 對於G
【Object-c基礎】預定義,條件編譯,陣列
1. 預定義:#define 在object-c中,跟C語言一樣都是採用#define才使用,但末尾是沒有分號的; 例子: #define PI 3.14 在之後即可引用,這點在iphone開發中一定每個組建的tag非常好用,並且可以集合放一個定義檔案中。 2. 條件編譯:#ifdef,
巨集定義與條件編譯的用處
#define 定義巨集 #undef 取消已定義的巨集 巨集定義常量與命令可以避免幻數 在巨集定義命名時候應該儘量清楚表明其用途。 函式型巨集定義的有點:儘管其和真正的函式相比有很多缺點,但只要小心使用還是會顯著提高程式碼的執行效率
c語言的巨集定義缺陷
| 考慮asert巨集的定義。 | 定義1:#define assert(e) if(!e) _assert_error (__FILE__, __LINE__ ) | 當 if(x>0 && y>0) asser
在C語言中 巨集定義是什麼?
巨集定義是C提供的三種預處理功能的其中一種,這三種預處理包括:巨集定義、檔案包含、條件編譯 巨集定義又稱為巨集代換、巨集替換,簡稱“巨集”。 格式:#define 識別符號 字串 其中的識別符號就是所謂的符號常量,也稱為“巨集名”。 預處理(預編譯)工作也叫做巨集展開:將巨集名替換為字串。 掌握"巨集"概念的
C語言__預處理(巨集定義、檔案包含、條件編譯)
C語言__預處理(巨集定義、檔案包含、條件編譯) 預處理簡單理解 1.C語言在對源程式進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include檔案包含指令),產生一個新的源程式(這個過程稱為編譯預處理),之後再進行通常的編譯
C語言入門(廿二)之預處理指令、巨集、條件編譯、檔案包含、typedef、const
預處理指令 什麼是預處理指令: 在我們的檔案翻譯成0和1之前做的操作我們稱之為預處理指令。一般情況預處理指令都是以#號開頭的。 巨集定義的格式 不帶引數的巨集定義: #define 巨集名 值 巨集定義的作用:
編譯預處理指令:檔案包含指令、巨集定義指令、條件編譯指令
編譯預處理指令:檔案包含指令、巨集定義指令、條件編譯指令。“#”開頭,不加分號“;” 1、檔案包含指令: #include<檔名> 標準目錄下搜尋 #include"檔名" 當前目錄下搜尋,再在標準目錄下搜尋 2、巨集定義指令: #define 巨集名 巨集文字 //巨集名習慣大寫 #
程式猿之---C語言細節9(巨集定義、max(a,b)巨集定義細節、大小端判斷、(int&)a什麼意思)
主要內容:巨集定義、max(a,b)巨集定義細節、大小端判斷、(int&)a什麼意思 #if 1 #include <stdio.h> // 注意空格 #define F (x) ((x) - 1) // F代表後面 #define F(x)
C語言~巨集操作大全(巨集定義、內建巨集、__FILE__、__LINE__、##用法)
當然巨集定義非常重要的,它可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。 下面列舉一些成熟軟體中常用得巨集定義 1,防止一個頭檔案被重複包含 #ifndef COMDEF_H #define COMDEF_H //標頭檔案內容 … #endif
C語言巨集定義、巨集函式、內建巨集與常用巨集
前言: 在C語言中,變數型別、迴圈控制、基礎語法等與其他高階語言基本無異;而C語言(C++)特有的兩把雙刃劍指標和巨集定義/巨集函式使得C語言在底層開發中披荊斬棘、無所不能。這兩個概念涉及範圍比較廣,其分支點也比較多,可謂星羅棋佈,但這每顆星都足以照亮C語言因其