linux下C语言常见宏定义
(1) 写一个“标准”宏,这个宏输入两个参数并返回较小的一个 。
#define MIN(a,b) ((a) > (b) ? (a) :(b))
(2)表明1年中有多少秒(忽略闰年问题):
#define SUM_YEAR_SECONDES (365*24*60*60)
(3)一句C语言实现把0x2000地址处的整型变量第7位置1,其他位不变。
*(volatile unsigned int *)0x2000 | = 1<<6;
(4)写两个宏, 分别用来把第n位设置为1(设置位)或0(清除位), 不改变其它位
#define set_bit(val,n) ( val) |=1<<n-1`
#define cel_bit(val,n) (val) &= ~(1<<n-1)//把某位反转^=
(5)写两个宏,求分别用来读取/设置ARM处理器(32位)中的某个寄存器。
#define read_reg(addr) *((volatile unsigned int *)addr)
#define write_reg(addr,val) *((volatile unsigned int *) addr) = val
6)用宏实现已知结构体的某个成员地址,返回结构体首地址。
/** 参数: type -- 这是一个 class (结构体类型)类型,member-designator 是一个有效的成员指示器。
* member-designator -- 这是一个 class 类型的成员指示器(具体的结构体变量)。
* 返回值: 该宏返回类型为 size_t 的值,表示 type 中成员的偏移量*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
offsetof(type, member-designator)(获取偏移量)
实例:
#include <stddef.h>
#include <stdio.h>
struct address {
char name[50];
char street[50];
int phone;};
int main()
{
printf("address 结构中的 name 偏移 = %ld 字节。\n",offsetof(struct address, name));
printf("address 结构中的 street 偏移 = %ld 字节。\n",offsetof(struct address, street));
printf("address 结构中的 phone 偏移 = %ld 字节。\n",offsetof(struct address, phone));
return(0);
}
执行结果:
address 结构中的 name 偏移 = 0 字节。
address 结构中的 street 偏移 = 50 字节。
address 结构中的 phone 偏移 = 100 字节。
(7)container_of()
container_of()的作用就是通过一个结构变量中一个成员的地址找到这个结构体变量的首地址。container_of(ptr,type,member),这里面有ptr,type,member分别代表指针、类型、成员。
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
// 如果开发者使用时输入的参数有问题:ptr与member类型不匹配,编译时便会有warnning, 但是如果去掉改行,那个就没有了,而这个警告恰恰是必须的 。
//typeof 获取当前类型
(type *)( (char *)__mptr - offsetof(type,member) );})
(8) Linux中双向链表的经典实现:
struct list_head {
struct list_head *next, *prev;
};
(9)宏与粘合剂(##)
在宏定义中,有#x与x##n两种,其中比较好理解的是##,##代表粘合剂,就是把前后两个合法的字符串连接起来 。
而#代表参数替换,比如正常我们定义z这样的一个宏:
#define SQR(x) printf("The square of x is %d.\n", ((x)*(x)));
但是字符串中的x是无法被替换掉的
所以输出为:
当SQR(8);
则输出为:The square of x is 64.
所以我们使用#x
#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x)));
输出为 :
再使用:SQR(8);
则输出的是:The square of 8 is 64.
(10) 时间回绕 -jiffie
extern unsigned long volatile jiffies;