2.重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
- typedef
unsigned char boolean; - typedef
unsigned long int uint32; - typedef
unsigned short uint16; - typedef
unsigned char uint8; - typedef
signed long int int32; - typedef
signed short int16; - typedef
signed char int8;
- #define
MEM_B( x ) ( *( (int8 *) (x) ) ) - #define
MEM_W( x ) ( *( (uint16 *) (x) ) )
- #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)中的偏移量
6,得到一个结构体中field所占用的字节数
7,按照LSB格式把两个字节转化为一个Word
8,按照LSB格式把一个Word转化为两个字节
- #define
FLOPW( ray, val ) \ - "white-space:pre">
(ray)[0] = ((val) / 256); \ - "white-space:pre">
(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的倍数
12,将一个字母转换为大写
- #define
UPCASE( c ) ( ((c) >= ''a'' && (c) <= ''z'') ? ((c) - 0x20) : (c) )
13,判断字符是不是10进值的数字
14,判断字符是不是16进值的数字
- #define
HEXCHK( c ) ( ((c) >= ''0'' && (c) <= ''9'') ||\ -
((c) >= ''A'' && (c) <= ''F'') ||\ -
((c) >= ''a'' && (c) <= ''f'') )
15,防止溢出的一个方法
16,返回数组元素的个数
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
C语言中的宏定义
C语言中的宏定义也叫做预处理命令,预处理命令是C语言本身的组成部分,不能直接对它们进行编译。
1.基本概念;
1>预处理不是C语句,是在编译前进行的
2>预处理功能主要用于下3种情况:
Ø 宏定义
Ø 文件包含
Ø 条件编译
3>宏是在编译前进行的,程序不能直接对它们进行编译,由预处理程序先进行替换。
说明:
Ø 一个预处理命令占用一个单独的行,命令末尾不使用分号作为结束符。
Ø 宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,它只做字符替换,不分配内存空间。
2.不带参数的宏
1>用一个指定的标识符(即名字)来代替一个字符串,它的一般形式为
#define 标识符 字符串
Eg:
#define MAX_NUM 100
它的作用是在本程序文件中使用指定的标识符MAX_NUM来替代 100这个字符串。
2>宏定义是用宏名代替一个字符串,也就是做简单的置换,不做正确性检查。(预编译时不做任何语法检查,只有在编译已被宏展开后的源程序时才会发现语法错误并报错)
3>宏定义不是C语句,不必在行末加分号。如果加了分号则会连分号一起进行替换
4>#definde出现在A处,则宏名的有效范围为定义命令之后到本源文件之后到本源文件结尾。
5>可以通过#undef命令终止宏定义的作用域.
#define MAX_NUM 100;
Void main()
{
……………………. MAX_NUM的作用范围
………………….
};
#undedf MAX_NUM
f()
{
………………………….
…………………………
}
说明:当解除宏定义时,只需要指出宏标识符而不必给出后面的字符串。
6>在进行宏定义时,可以引用已定义的宏名,可以层层置换(即宏可以嵌套)
#define PI 3.141596
#define R 3.0
#define L 2*PI*R
#define S PI*R*R
7>对程序中使用双引号括起来的字符串,即使与宏名相同,也不进行置换。
eg;
printf(“L =%f\n,s=%f\n”,L,S);
在printf中双引号内的L不进行替换,双引号外的进行替换。