1. 程序的编译与链接
平时我们写的都是后缀为.c的文件,经过编译后生成目标文件(.obj),最后通过链接后生成可执行程序(.exe)
源文件 ——> 编译 ——> 链接 ——> 可执行程序
而编译部分又包括: 预处理、编译、汇编
预处理:头文件的包含、#define定义符号的替换、注释的删除
编译:把C语言代码翻译成汇编代码
汇编:把汇编指令翻译成二进制指令
2. 预定义符号
__FILE__
__LINE__
__DATE__
__TIME__
__STDC__//进行编译的源文件
//文件当前的行号
//文件被编译的日期
//文件被编译的时间
//如果编译器遵循ANSI C,其值为1,否则未定义
int main()
{
printf("%s\n", __FILE__);//进行编译的源文件
printf("%ld\n", __LINE__); //文件当前的行号
printf("%s\n", __DATE__); //文件被编译的日期
printf("%s\n", __TIME__); //文件被编译的时间
printf("%d\n", __STDC__); //如果编译器遵循ANSI C,其值为1,否则未定义
return 0;
}
因为__STDC__未定义,所以编译器比遵循标准C规定
注释掉之后:
3. #define
3.1 #define定义标识符
用define定义的标识符会在预处理阶段被替换成它所表示的常量,比如:
#define M 100
int main()
{
int m = 0;
m = M;//在预处理阶段就替换成了 m = 100;
printf("%d", m);
return 0;
}
3.2 #define定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏
例如:
#define SQUARE(M) M*M
int main()
{
printf("%d", SQUARE(10));
return 0;
}
但只是这样并不严谨,实现宏的定义圆括号在大多时候都是不可缺少的
#define DOUBLE(M) M+M
int main()
{
//我们期望的结果是5*20
printf("%d", 5* DOUBLE(10));
//但实际结果是60
//因为代码被替换成了 5 * 10 + 10
return 0;
}
#define DOUBLE(M) ((M)+(M))
//加括号后就会得到我们期望的结果了
int main()
{
printf("%d", 5* DOUBLE(10));
// 5* ((10) + (10))
return 0;
}
乍看上去宏和函数好像一样
实际上他们有许多不同:
1.从执行速度上宏的优势更明显,因为函数还有调用花费时间
2.从参数限制的角度看宏更好用,因为它不规定参数必须是什么类型
3.从调试的角度看函数更好用,因为宏在预处理的时候就被替换了,不便调试,而函数可以一步一步的调试
4.从代码长度的角度看函数更好用,因为函数只写一次定义,可以直接调用,而宏每次都要替换,会使程序的长读大幅度增长
5.函数可以递归,宏不可以递归
4.条件编译
在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃就可以用条件编译指令。
比如说:
调试性的代码,删除可惜,保留又碍事,所以我们可以选择性的编译
#define DEBUG
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i;
//如果定义了DEBUG就执行下面的代码
#ifdef DEBUG
printf("%d ", arr[i]);
//条件编译结束标志
#endif
}
return 0;
}
//#define DEBUG
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i;
//如果定义了DEBUG就执行下面的代码
#ifdef DEBUG
printf("%d ", arr[i]);
//条件编译结束标志
#endif
}
return 0;
}
//#define DEBUG
int main()
{
int arr[10] = { 0 };
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i;
//如果没有定义DEBUG就执行下面的代码
#ifndef DEBUG
printf("%d ", arr[i]);
//条件编译结束标志
#endif
}
return 0;
}
常见的条件编译还有:
#if 常量表达式
…
#endif
例如:
#define M 1
int main()
{
#if M
printf("YES");
#endif
return 0;
}
还有多分支的条件编译:
#if 常量表达式
…
#elif 常量表达式
…
#endif
例如:
#define M 0
#define N 1
int main()
{
#if M
printf("YES");
#elif N
printf("NO");
#endif
return 0;
}