程序环境和预处理

简介: 程序环境和预处理

1. 程序的翻译环境和执行环境

翻译环境:在这个环境中源代码被转换为可执行的机器指令。

执行环境:它用于实际执行代码。

2. 详解编译+链接

首先我们看一张图:

在一个工程中,我们需要协作,那必须创建多个源文件(test.c),那么每个源文件经过编译器编译变为test.obj,再由链接器加链接库把test.obj文件变为test.exe可执行文件。


接下来,我们具体看过程:


其实笼统地来说,由.c文件到.exe文件,只有两步,编译和链接,但是细分的话,有四步:

所以仔细看图以后,我们可以知道,其实到可执行文件有四步,预处理,编译,汇编,链接。


编译过程中符号汇总,汇编产生的符号表,以及后面链接时要进行的符号表的合并和重定位。


都是非常重要的。


3.运行环境

程序执行的过程:

1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

2. 程序的执行便开始。接着便调用 main 函数。( 程序的入口)

3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static )内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。

4. 终止程序。正常终止 main 函数;也有可能是意外终止。

4.预处理

1 预定义符号

__FILE__       // 进行编译的源文件

__LINE__     // 文件当前的行号

__DATE__     // 文件被编译的日期

__TIME__     // 文件被编译的时间

__STDC__     // 如果编译器遵循 ANSI C ,其值为 1 ,否则未定义

printf ( "file:%s line:%d\n" , __FILE__ , __LINE__ );可以通过打印字符串的方式来显示。

2.#define 定义标识符

#define +标识符+符号内容

(注意的一点是,#define定义标识符最后尽量不要加;(分号),因为会将分号当作标识符内容一起替换掉。)

比如:

#define MAX 1000;
#define MAX 1000
int main()
{ 
   int a=MAX;
   return 0;
}

为了防止分号多出现这种情况,尽量不要加;。

3.续行符

如果定义的stuff过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)

#define DEBUG_PRINT printf("file:%s\tline:%d\t \
                         date:%s\ttime:%s\n" ,\
                         __FILE__,__LINE__ ,\
                         __DATE__,__TIME__ )  

其实相当于\转义了回车,当内容太长的时候,就可以利用续行符来解决,其实是在同一行。


4.#define定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义

宏(define macro)。

下面是宏的申明方式:

#define name( parament-list ) stuff

其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。

注意:

参数列表的左括号必须与name紧邻。

如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分

举例说明:

#define square(x) ((x)*(x))
int main()
{
  int a=5;
  square(a+1);
}
会换成:
((5+1)*(5+1))

在写宏时,不要吝啬括号,能加括号的地方就加括号,会防止很多运算符优先级打乱预期的结果。

#define square(x) x*x
int main()
{
  int a=2;
  Add(a+1);
}
会换成:
2+1*2+1

从而没有到达我们平方的预期。


5.宏替换规则

在程序中扩展 #define 定义符号和宏时,需要涉及几个步骤:

1. 在调用宏时,首先对参数进行检查,看看是否包含任何由 #define 定义的符号。如果是,它们首先被替换。

2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

3. 最后,再次对结果文件进行扫描,看看它是否包含任何由 #define 定义的符号。如果是,就重复上述处理过程。

注意:

1. 宏参数和 #define 定义中可以出现其他 #define 定义的符号。 但是对于宏,不能出现递归。

2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。


目录
相关文章
|
5月前
|
编译器 Linux C语言
程序环境和预处理(2)
程序环境和预处理(2)
37 0
|
5月前
|
存储 自然语言处理 程序员
程序环境和预处理(1)
程序环境和预处理(1)
48 0
|
6月前
|
存储 编译器 程序员
程序环境和预处理
程序环境和预处理
|
6月前
|
存储 编译器 程序员
零基础也能学会的『程序环境和预处理』
零基础也能学会的『程序环境和预处理』
|
6月前
|
存储 自然语言处理 编译器
程序环境和预处理(详解)
程序环境和预处理(详解)
|
存储 编译器 程序员
【C】程序环境和预处理
在ANSI C的任何一种实现中,存在两个不同的环境。
|
存储 自然语言处理 程序员
【程序环境与预处理】(一)
【程序环境与预处理】(一)
85 0
|
编译器 Linux C++
【程序环境与预处理】(二)
【程序环境与预处理】(二)
86 0
|
6月前
【程序环境与预处理玩转指南】(中)
【程序环境与预处理玩转指南】
|
6月前
|
存储 编译器 程序员
【程序环境与预处理玩转指南】(上)
【程序环境与预处理玩转指南】