预定义符号
—FILE — //进行编译的源文件
—LINE — //文件当前的行号
—DATE — //文件被编译的日期
—TIME — //文件被编译的时间
—STDC — //如果编译器遵循ANSI C,其值为1,否则未定义
printf("file:%s line:%d\n", __FILE__, __LINE__);
#define
#define 定义标识符
#define MAX 1000 #define reg register
//为 register这个关键字,创建一个简短的名字
#define do_forever for(; ;)
//用更形象的符号来替换一种实现
#define CASE break;case
//在写case语句的时候自动把 break写上。
// 如果定义的 stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠==(续行符)==。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \
date:%s\ttime:%s\n" ,\
—FILE —, —LINE — , \
—DATE —, —TIME — )
#define 定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)
#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
注意:
参数列表的左括号必须与name紧邻
否则就会被误认为是定义标识符
#include<stdio.h>
#define SQUARE(X) ((X)*(X))
int main()
{
int r = SQUARE(5);
printf("%d", r);
return 0;
}

注意:1.宏参数和#define 定义中而可以出现其他的 #define 定义的符号
但是对于宏,不能出现递归
2.当预处理器搜素#define 定义的符号时,字符串常量的内容不被搜索
#和##

对于printf 函数可以这样由几个字符串一起 构成一个


#N 转换它所对应的字符串
就变为 printf (“the value of “a” ”is %d\n",a); 几个字符串连一起 成一句
当然,也可以以不同类型打印


可以把位于两边的符号合成一个符号
#include<stdio.h>
#define CAT(Class,Num) Class##Num
int main()
{
int Class106 = 100;
printf("%d",CAT(Class, 106)); //printf("%d",Class106);
return 0;
}

带副作用的宏参数
当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。
例如:
x+1; //不带副作用
x++; //带有副作用
#include<stdio.h>
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int main()
{
int a = 3;
int b = 5;
int m = MAX(a++, b++);
//((a++)>(b++)?(a++):(b++))
//3>5? //后来a=4,b=6
//条件不成立 执行 b++ m=6//后来b=7 //没执行语句,就不去运算了,a=4不去加了
printf("m=%d\n", m);//6
printf("a=%d b=%d", a, b);//4 7
return 0;
}

宏和函数做对比
//宏
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
// 函数
int Max(int x, int y)
{
return (x > y ? x : y);
}
用宏来比较两个数最好
原因:
1.宏比函数在程序规模上和速度上更胜一筹
2.宏是类型无关的
宏
MAX(2,3)可以
MAX(1.5,3.6)也可以
而函数
Max(2,3) 可以
Max(1.5,3.6)不可以,参数类型不符合
宏缺点:
- 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。
- 宏是没法调试的。
(在预处理的时候#define 改替换的替换了,在调试的时候虽然看着原来的代码,但是却被改得不一样了) - 宏由于类型无关,也就不够严谨。
- 宏可能会带来运算符优先级的问题,导致程容易出现错。
(即,该加括号就加,不要吝啬括号)
宏有时候可以做到函数做不到的事情
(宏参数可以出现类型,但是函数不可以)
#include<stdio.h>
#define MALLOC(NUM,TYPE)\
(TYPE*)malloc((NUM)*sizeof(TYPE))
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
// int *p=MALLOC(10,int);
}
总:足够简单用宏,复杂易错用函数
命名约定
一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。
把宏名全部大写
函数名不要全部大写
undef
用于移除一个宏定义
#include<stdio.h>
#define MAX 100
int main()
{
printf("%d", M);
#undef M
printf("%d", M);
return 0;
}

命令行定义
许多C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程
例如,在linux 的gcc 编译器上,对编译的程序进行再次命令
条件编译
对于调试性的代码,删了可惜,留着碍事,于是可以选择性编译
#include<stdio.h>
//#define _DEBUG_
int main()
{
int i = 0;
int arr[10] = { 0 };
for (i = 0;i < 10;i++)
{
arr[i] = i;
#ifdef _DEBUG_
printf("%d", arr[i]);
#endif
}
return 0;
}


常见的条件编译指令:
1.
#if 常量表达式
//…
#endif
//常量表达式由预处理器求值。
如:
#define —DEBUG__ 1
#if —DEBUG—
//..
#endif
也可
#if 1//条件为真执行
//...
#endif
#if 0//条件为假不执行
//...
#endif
#if 2==3//条件为假不执行
//...
#endif
2.多个分支的条件编译
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif
如:
#include<stdio.h>
#define M 6
int main()
{
#if M < 5
printf("hehe");
#elif M==5
printf("haha");
#else
printf("heihei");
#endif
return 0;
}
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
#include<stdio.h>
#define MAx 100
int main()
{
#if defined(MAX)
printf("max\n");
#endif
return 0;
}
//#define MAx 100
int main()
{
#if !defined(MAX)
printf("max\n");
#endif
return 0;
}
4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
398

被折叠的 条评论
为什么被折叠?



