C语言宏的使用小结
来源:互联网 发布:java 构造函数返回值 编辑:程序博客网 时间:2024/05/18 22:54
1.防止一个头文件被重复包含
#ifndef __HEAD_H_#define __HEAD_H_#include <stdio.h>......#endif
2.得到指定地址上的一个字节或字
#define MEM_BYTE(x) (*((char *)(x)))#define MEM_WORD(x) (*((short *)(x)))
3. 得到一个field在结构体(struct)中的偏移量
#define GET_OFFSET_STRUCT(type,field) (&(((type *)0)->field))
说明:
这里涉及到结构体中成员边界对齐的问题,相同的结构体在不同的CPU和编译器上会得到不同的结果。
如下面的代码,所得到的偏移是不同的。
测试的环境是:
- MacBookPro OS 10.12.3 + MacOS gcc.
- sizeof(char)=1,sizeof(short)=2,sizeof(int)=4,sizeof(long)=8,sizeof(float)=4
- sizeof(struct Student)=40=4+4+8+4+4*5
- sizeof(struct StudentPacked)=37=1+4+8+4+4*5
struct Student { char a; //offset=0 int b; //4 long c; //8 float d; //16 int e[5]; //20};struct StudentPacked { char a; //offset=0 int b; //1 long c; //5 float d; //13 int e[5]; //17}__attribute__((packed));
4.得到一个结构体中field所占用的字节数
#define GET_FIELD_SIZE(type,field) (sizeof(((type *)0)->field))
5.返回数组元素的个数
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a[0])))
6.使用__LINE__
等宏输出日志
printf("%s %s %d %s %s\n",__FILE__,__FUNCTION__,__LINE__,__DATE__,__TIME__);
输出结果为: ../src/UsefulC.c main 58 Feb 23 2017 01:55:08
7.宏定义中#
,##
的用法
#
表示把宏定义中的参数转化为字符串, ##
表示把宏定义中的参数连接起来,看实例:
#define STR(s) #s#define CONS(a,b) ((int)(a##e##b))printf(STR(vck)); // 输出"vck"printf("%d\n", CONS(2,3)); // 输出2000,即2e3=2*10^2
注意:
上面STR和CONS的参数是不能加括号的,就是说不能这样定义:
#define STR(s) #(s)
#define CONS(a,b) ((int)((a)##e##(b)))
深入一点,当宏参数是另一个宏的情况下,宏参数是不会展开的,是不是不知所云,举一个例子,
#define A 2#define STR(s) #s#define CONS(a,b) ((int)(a##e##b))printf(STR(A)); // 输出"A"printf("%d\n", CONS(A,A)); //CONS(A,A)被替换为AeA,编译出错了
如何避免这个错误呢,很简单,在加一个转换宏即可,代码如下,
#define A 2#define STR(s) _STR(s)#define CONS(a,b) _CONS(a,b)#define _STR(s) #s#define _CONS(a,b) ((int)(a##e##b))printf(STR(A));printf("%d\n", CONS(A,A));
定义_STR
这个转换宏后,从STR
到_STR
的替换,就实现了A
到2的替换,_CONS
类似。
这里在举一个实际的应用:
#define ___ANONYMOUS1(type, var, line) type var##line#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
例如:ANONYMOUS(static int);
,如果这条语句定义在源码里的第70行,那么相当于如下语句: static int _anonymous70;
说明如下:
第一层:ANONYMOUS(static int);
–> __ANONYMOUS0(static int, __LINE__);
第二层: –> ___ANONYMOUS1(static int, _anonymous, 70);
第三层: –> static int _anonymous70;
即每次只能解开当前层的宏,所以__LINE__
在第二层才能被解开;
- C语言宏定义的使用小结
- C语言宏的使用小结
- C语言小结--offsetof和container_of宏的使用
- C语言指针使用小结
- C语言指针使用小结
- C语言内存使用小结
- C语言typedef使用小结
- C语言的宏问题小结
- C语言中二维数组做参数的使用小结
- 黑马程序员-C语言const关键字的使用小结
- C语言宏定义小结
- C语言宏定义小结
- C语言宏定义小结
- 使用c语言调用python小结
- 使用c语言调用python小结
- 使用c语言调用python小结
- C语言宏的一些常规用法小结
- C语言宏的使用
- PAT-1001. 害死人不偿命的(3n+1)猜想
- xshell无法连接linux虚拟机
- openstack实现对数据的通用校验源码分析:validation(以nova为例)
- 使用虚拟机安装Linux系统时的一些问题
- 观察者设计模式
- C语言宏的使用小结
- JDK API文档的使用
- 目标和学习方法的重要性
- Linux 网络分析工具之tcpdump
- 10603UVA倒水
- VS2008中导入EXCEL文件数据(Unicode版本下)
- Android 查看及设置 SELinux 状态
- Android之HelloWorld
- 在MFC对话框中显示html网页