#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define trance(x,format) \
printf(#x " =% " #format "\n",x)
int main() {
char flag = '1';
trance(flag,c);
trance(flag,d);
char* name = "zifuchuanhua";
trance(name,s);
trance(name,x);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define trance(x,format) \
printf(#x " =% " #format "\n",x)
#define trance2(i) trance(salary ## i,d)
int main() {
int salary1 = 10000,salary2=1209,salary3=12345;
trance2(1);
trance2(2);
trance2(3);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define F(f) f(args)
#define args a,b
void test(int number1,int number2){
printf("%d + %d = %d\n",number1,number2,number1 + number2);
}
int main() {
int a=5;
int b=9;
F(test);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define STUDY( name) do{ \
printf("study %s\n",name); \
printf("work %s\n",name); \
printf("learn %s\n",name); \
printf("diy %s\n",name); \
}while(0);
int main() {
char name[] = "qrs";
STUDY(name);
return 0;
}
#ifndef xxxxx
#define xxxxx
#endif
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define DEBUG(fmt, ...) \
printf("[FILE: %s] [FUNCTION: %s] [LINE: %d] " fmt "\n", \
__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
int main() {
int x = 100;
int y = 200;
DEBUG("x = %d, y = %d", x, y);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
#define DEBUG_ON 1
#if DEBUG_ON
#define DEBUG(fmt, ...) \
printf("[FILE: %s] [FUNCTION: %s] [LINE: %d] " fmt "\n", \
__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define DEBUG(fmt,...)
#endif
int main() {
int x = 100;
int y = 200;
DEBUG("x = %d, y = %d", x, y);
return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/time.h>
//使用这一行或注释这一行
#define DEBUG_ON
#if DEBUG_ON
#define DEBUG(fmt, ...) \
printf("[FILE: %s] [FUNCTION: %s] [LINE: %d] " fmt "\n", \
__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#else
#define DEBUG(fmt,...)
#endif
int main() {
int x = 100;
int y = 200;
DEBUG("x = %d, y = %d", x, y);
return 0;
}
#define MEM_B(x) (*((byte *)(x)))
#define FPOS(type,field) ((dword) & ((type *)0)->field)
#define FSIZ(type,field) sizeof(((type*)O)->field)
#define WORD_LO(xxx) ((byte)((word)(xxx) & 255))
#define WORD_HI(xxx) ((byte)((word)(xxx) >> 8))
#define UPCASE(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 0X20):(c))
#define ARR_SlZE(a) (sizeof((a))/sizeof((a[0])))
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)
ptr 是指向结构体成员的指针;
type 是结构体类型名;
member 是结构体成员名。
该宏定义包含一个单独的表达式,它执行以下操作:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
功能:根据结构体变量成员施址获取整个结构体的存储空间首地址
参数:
ptr:结构体变量的成员地址
type:结构体类型
member:结构体成员
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
举个例子,来简单分析一下 container_of 内部实现机制。
例如:
struct test{
int a;
short char b;c;
};
struct test *p = (struct test *)malloc(sizeof(struct test));
test_function(&(p->b));
int test_function(short *addr_b){//获取 struct test 结构体空间的首地址
struct addr = test *addr;
container_of(addr_b,struct test,b);
}
展开 container_of 宏,探究内部的实现:
typeof ( ( (struct test *)0 )->b ) ; (1)
typeof ( ( (struct test *)0 )->b ) *__mptr = addr_b ; (2)
(struct test *)( (char *)__mptr - offsetof(struct test,b)) (3)
(1) 获取成员变量 b 的类型 ,这里获取的就是 short 类型。这是 GNU_C 的扩展语法。
(2) 用获取的变量类型,定义了一个指针变量 __mptr ,并且将成员变量 b 的首地址赋值给它
(3) 这里的 offsetof(struct test,b)是用来计算成员 b 在这个 struct test结构体的偏移。 __mptr是成员 b 的首地址, 现在 减去成员 b 在结构体里面的偏移值,算出来的是不是这个结构体的首地址呀 。
(1)函数调用时,先求出实参表达式的值,然后带入形参带参数的宏只进行简单的字符替换;
(2)函数调用是在程序运行时处理,分配临时内存;而宏展开(函函数),是在编译时进行的,展开时是不分配内存,也没有返回值,也没有值传递
(3)宏的参数没有类型,只是一个符号《展开时带入到指定字符串中。
(4)使用宏次数多时,宏展开后源程序变长,函数调用不会使源程序变长;
(5)宏替换只占用编译时间,不占用运行时间而函数调用占用的是运行时间(分配内存,传递参数,执行函数体)。