文章目录
1.在ANSI C的任何一种实现中,存在两个不同的环境
1)翻译环境
在这个环境中源代码被转化为可执行的机器指令
2)执行环境
用于执行代码
3)图解
2.翻译过程(编译&&链接)
1)编译与链接的基本概念
一个源文件test.c在编译器经过编译和链接两个过程而生成可执行文件test.exe,而编译又分为分为三个阶段:预处理(预编译)、编译、汇编,(翻译过程)。而可执行文件生成在运行环境可以直接运行。下面是程序编译的过程。
2)程序编译过程
- 组成一个程序的每个源文件通过编译过程分别转换为目标文件
- 每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序。
- 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
a.预处理(文本操作)
gcc -E test.c->test.i
1.#include 头文件的包含
2.注释的删除
3.#define定义符号的替换
预处理详解
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;
}
b.编译
gcc -S test.i->test.s//汇编
把c语言代码换为汇编代码
1.语法分析:保证语法正确 比如变量类型是否定义
2.语义分析:检查语法结构的含义,包括静态语义和动态语义 比如:变量值是否相等
3.词法分析:判断单词是否拼写正确
4.符号汇总
c.汇编
gcc -c test.s->test.o
把汇编代码转换为机器指令
形成符号表
3)链接过程
1.符号表的合并与重定义
2.合并段表
3.运行环境
1.程序必须载入内存中,在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2.程序的执行变开始,接着调用函数
3.开始执行程序代码,这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4.终止程序,正常终止main函数,也有可能是意外终止。
4.条件编译
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.多个分支的条件编译
#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