在ANSI C的任何一种实现中,存在两个不同的环境
- 翻译环境,在这个环境中源代码被转化为可执行的机器指令
- 执行环境,用于执行代码
编译+链接
翻译环境
程序编译过程如下:
- 组成一个程序的每个源文件通过编译过程分别转换为目标文件
- 每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序。
- 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
- 一个源文件test.c变为可执行程序的过程如下所示:
预处理:(文本操作)
gcc -E
test.c->test.i
1.#include 头文件的包含
2.注释的删除
3.#define定义符号的替换
编译
gcc -S
test.i->test.s//汇编
把c语言代码换为汇编代码
1.语法分析:保证语法正确 比如变量类型是否定义
2.语义分析:检查语法结构的含义,包括静态语义和动态语义 比如:变量值是否相等
3.符号分析
4.词法分析:判断单词是否拼写正确
汇编
gcc -c
test.s->test.o
把汇编代码转换为机器指令
形成符号表
链接
1.符号表的合并与重定义
2.合并段表
运行环境
1.程序必须载入内存中,在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2.程序的执行变开始,接着调用函数
3.开始执行程序代码,这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4.终止程序,正常终止main函数,也有可能是意外终止。
预处理详解
FILE //进行编译的源代码
LTNE //文件当前的行号
DATE //文件被编译的日期
TIME //文件被编译的时间
STDC //如果编译器遵循ANSI C,其值为1,否则未定义
eg:显示文件名与时间
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("file:%s line:%d %d\n", __FILE__, __LINE__, i);
}
system("pause");
return 0;
}
条件编译
1.
#if 常量表达式
///....
#endif
eg:
#define _DEGUE_ 0
int main()
{
int arr[8];
for (int i = 0; i < 8; i++)
{
arr[i] = i;
#if DEGUE
printf("%d", arr[i]);
#endif
}
for (int i = 0; i < 8; i++)
{
arr[i] = i;
#if DEGUE
printf("%d", arr[i]);
#endif
}
system("pause");
2.多个分支的条件编译
扫描二维码关注公众号,回复:
3298751 查看本文章
#if 常量表达式
//..
#elif 常量表达式
//...
#endif
3.判断是否被定义
#if defined(symbol
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
#define MAX 0
int main()
{
#if defined(MAX)//if判断的是是否定义
printf("hehe");
#endif MAX
system("pause");
}
#if defined(xx)#ifdef xx是一对
#if !defined(xx)与 #ifndef xx是一对
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();
#end
#endif
文件包含
#include <> 库提供的,直接从库里去查找
- #include “” 查找,先从当前工程里查找,再从库里面查找。