1. #define
1-1 预定义符号(语法内置的)
_FILE_ //进行编译的源文件
_LINE_ //文件当前行号
_DATE_ //文件被编译日期
_TIME_ //文件被编译时间
_STDC_ //如果编译器遵循ANSI C,值为1
否则未定义
示例:
printf("filr:%d line:%d\n",_FILE_,_LINE_);
1-2. #define定义标识符
#define MAX 1000 //别用分号‘;’
续行符
’\‘
将换行转义成不是换行
1-3. #define定义宏
#define name(参数列表)被替换的文本
name和参数列表之间要紧贴,不能有空格
示例:
#define square(x)x*x //求x的平方
(x)里面的x替换x*x里面的x
1-3-1. 替换规则
#define square(x)x*x
1)调用宏时。检查参数,替换参数 //替换到(x)中
2)参数替换到被替换的文本中 //替换到x*x中
3)是替换,不是计算
假设x是(100+2)
是直接将(100+2)替换成参数
(100+2)*(100+2) //正确
并不是将(100+2)的计算结果(102)替换成参数
102*102 //error
4)宏不能递归
5)字符、字符串不能替换成参数
1-4. #和##
printf("hello" "world\n"); //输出结果:hello world
2个字符串可以合并成1个字符串
1-4-1. #
#:把参数转换成参数对应的字符串
如果前后都是字符串,相当于把字符串插入字符串中
//定义
#define PRINT(N) printf("the values of "#N" is %d\n",N)
#N:不是N的值
而是N的字符串“N"
"the values of " #N " is %d\n" //3个都是字符串
//调用
int a = 10;
PRINT(a);
对应上面定义的:
(N):a的值
#N:a对应的字符串”a“
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define PRINT(N) printf("the values of "#N" is %d\n",N)
int main()
{
int a = 10;
PRINT(a);
//替换规则
//printf("the values of ""a"" is %d\n",10);
return 0;
}
1-4-2. ##
##:把2个符号合并成1个符号
//定义
#define CAT(Hello,World)Hello##World
//调用
int HelloWolrd = 20240904;
printf("%d\n",CAT(Hello,World));
把Hello,World这2个符号合并成HelloWolrd这1个符号
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//定义
#define CAT(Hello, World)Hello##World //##把Hello、World两个符号合并成HelloWorld一个符号
int main()
{
//调用
int HelloWorld = 20240904;
printf("%d\n", CAT(Hello, World));
return 0;
}
1-5. 带副作用的宏参数
a++;
1-6. 宏和函数
//宏
#define Max(x,y)((x) > (y) ? (x ):(y))
//函数
int Max(int x,int y)
{
return (x > y ? x : y);
}
宏适合更多类型
函数有类型限制
1-7 命令行定义
int arr[SZ];//SZ未定义
gcc -D SZ = 0 xx.c
1-8. 条件编译
#if
语句;
#endef
...
#ifdef
语句;
#endif
...
1-9. 文件包含
防止头文件被重复多次包含【包含一次执行一次】
2种解决方法
方法1:
#ifndef _TEST_H_
#define _TEST_H_
方法2:
#progma once
1-10. <>和“”的区别
查找路径不同
<>:
直接去库目录下查找
“”:
分2步
1)先去代码所在路径下查找。未找到,进行第2步
2)去库目录下查找
2. offsetof宏的实现
offsetof(type,member)
起始位置为0时,地址和偏移量相同
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stddef.h>
struct S
{
char c1;
char c2;
int i;
};
#define OFFSETOF(type,m_name) (size_t)&(((type*)0)->m_name)
int main()
{
struct S s = { 0 };
printf("%d\n", OFFSETOF(struct S, c1));
printf("%d\n", OFFSETOF(struct S, c2));
printf("%d\n", OFFSETOF(struct S, i));
return 0;
}