程序环境和预处理

一,C语言程序的运行

C语言程序会从.c文件一步一步转化为.exe可执行文件,

一般分为三个阶段:编译.链接,运行

编译细分为:预处理,编译,汇编

编译

预处理

        在预处理阶段,会将程序里面的宏定义,预处理命令,以及注释等替换,生成.i文件,注释被替换为一个空格,头文件会包含

编译

        在编译阶段,会将C语言程序翻译为汇编语言生成.s文件,并进行

        1.词法分析    2.语义分析    3.语法分析    4.符号汇总

汇编

        生成符号表,并将汇编代码翻译为二进制命令,生成.obj文件

链接

        将目标文件和链接库链接,合成段表,符号表的合并和重定义,生成可执行的二进制程序

运行

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

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

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

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

二.预处理命令

1.预处理符号

__FILE__      //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__    //文件被编译的日期
__TIME__    //文件被编译的时间
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

2.define定义宏

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

        下面是宏的申明方式: #define name( parament-list ) stuff 其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。

注意: 参数列表的左括号必须与name紧邻。 如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

宏本质上只是在预处理中对其替换,并不是像函数那样;所以如果不注意就会出现各种问题

比如这个宏定义

#define SQUARE( x ) x * x

如果我这么使用     SQUARE( 2 + 1)    结果就会变成2+1*2+1=5,而不是9,所以我们在定义宏的时候尽量将每一个参数都使用括号

#define SQUARE( x ) (x) * (x)

这样就能避免因为操作符顺序出现的问题,

3.#define 替换规则

        在程序中扩展#define定义符号和宏时,需要涉及几个步骤。 1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。 2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。 3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。 注意: 1. 宏参数和#define 定义中可以出现其他#define定义的变量。但是对于宏,不能出现递归。 2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

4.#和##

        使用 # ,把一个宏参数变成对应的字符串。比如

#define PRINT(FORMAT, VALUE)\
 printf("the value of " #VALUE "is "FORMAT "\n", VALUE);
PRINT("%d", 3*3);

结果是the value of 3*3 is 9,

        ##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符,比如

#define ADD_TO_SUM(num, value) \
 sum##num = value;
...
ADD_TO_SUM(2, 10);//作用是:给sum1赋值为10.

这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。

5.#undef

        这条指令用于移除一个宏定义。如果现存的一个名字需要被重新定义,那么它的旧名字就可以使用这个使其被移除。

三.条件编译

常见的条件编译指令:

1. #if 常量表达式 //... #endif //常量表达式由预处理器求值。 如:

#define __DEBUG__ 1
#if __DEBUG__ 
...
#endif

2.多个分支的条件编译 

#if 常量表达式
 //...
#elif 常量表达式
 //...
#else
 //...
#endif

3.判断是否被定义 

#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol

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();
     #endif
#endif

        

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值