前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序环境和预处理

程序环境和预处理

作者头像
The sky
发布2023-04-12 14:53:22
3460
发布2023-04-12 14:53:22
举报
文章被收录于专栏:C++的逆袭之路

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定义标识符最后尽量不要加;(分号),因为会将分号当作标识符内容一起替换掉。)

比如:

代码语言:javascript
复制
#define MAX 1000;
#define MAX 1000


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

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

 3.续行符

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

代码语言:javascript
复制
#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的一部分

举例说明:

代码语言:javascript
复制
#define square(x) ((x)*(x))

int main()
{
  int a=5;
  square(a+1);
}

会换成:
((5+1)*(5+1))

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

代码语言:javascript
复制
#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定义的符号的时候,字符串常量的内容并不被搜索。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 程序的翻译环境和执行环境
  • 2. 详解编译+链接
  • 3.运行环境
  • 4.预处理
    • 1 预定义符号
      • 2.#define 定义标识符
        •  3.续行符
          • 4.#define定义宏
            •  5.宏替换规则
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档