test.c 编译环境-> test.exe ->执行/运行环境
编译环境:
编译成test.obj与链接库通过 链接器 生成可执行程序... 编译(预处理,编译,汇编)和链接
预处理阶段 ->进行文本操作: 1.完成了头文件包含 2.#define定义的符号和宏的替换 3.注释删除
编译阶段 -> 把代码转化成汇编代码:1.语法分析 2.词法分析 3.语义分析 4.符号汇总
汇编阶段 -> 把汇编代码转化成机器指令(二进制指令 ):1.生成符号表 test.o为elf格式
链接阶段 -> 把多个目标文件和链接库进行链接 :1.合并段表 2.符号表的合并和重定位
运行环境:
- 过程:1.载入内存,有操作系统由操作系统完成。独立环境中,由手工安排。
2.程序开始执行,调用main函数
3.执行代码,使用一个运行时的堆栈stack,存储局部变量和返回值。同时程序也可使用静态内存,在执行过程中一直保留值
4.终止程序。正常终止main函数,可能意外终止
预定义符号:
__FILE__ __LINE__ __DATE__ __TIME__
运行文件的地址,行数,运行日期,运行时间: __STDC__如果编译器遵循ANSI C,其值为1,否则未定义
条件编译:
1.#if 常量表达式。。。#endif 常量表达式值为0其中不进行编译
#if 0
int main()
{
printf("%d", 2);
return 0;
}
#endif
2.多分支条件编译#if 常量表达式。。。#elif(*n)常量表达式。。。#else。。#endif如果第一个表达式值为真,不继续执行后面语句。
#define M 20
int main()
{
#if M>30
printf("M>30\n");
#elif M>40
printf("M>40\n");
#else
printf("haha\n");
#endif
return 0;
}
3.判断是否定义,#ifdef name...#endif
如果name定义,中间参与编译 另一种写法#if (!)defined(TEST)...#endif
#define A 10
int main()
{
#ifdef A
printf("%d\n", A);
#endif
#if !defined(A)
printf("%d", 90);
#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 option1
msdos_version_option1();
#endif
#endif
头文件:
库文件包含:
C语言库中提供的函数头文件用<> #include<stdio.h>
本地文件包含:
自定义函数用"" #include "add.h"
区别:
"" 自己代码所在的目录下查找,如果第1不找不到,则在库函数的头文件目录下查找
<>直接去库函数头文件所在的目录下查找
防止文件多次调用:
1.#pragam once
2.#ifndef __ADD_H__\n#define__ADD_H__....#endif(大小写无所谓)
其余预指令:
#error #pragma #line ...自己了解 #pragam pack(n)编译选项,结构体,表示n字节对对齐