【C语言】编译和链接

目录

1.翻译环境和运行环境

2.翻译环境

2.1预处理

(1)预定义符号

(2)define定义常量

 (3)define定义宏

(4)宏规则及其特点

(5)操作符#和##

(6)命名约定

(7)#undef

(8)条件编译

2.2编译

2.3汇编

3.链接

4.运行环境


1.翻译环境和运行环境

  在ANSI C的任何⼀种实现中,存在两个不同的环境

  第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
  第二种是执行环境,它用于实际执行代码。

2.翻译环境

翻译环境由编译链接两大内容组成,其中编译又依靠预编译编译汇编三个过程

2.1预处理

(1)预定义符号

  1. __FILE__: 它表示当前源文件的名称。
  2. __LINE__: 它表示当前源文件的行号。
  3. __DATE__: 它表示源文件被编译的日期。
  4. __TIME__: 它表示源文件被编译的时间。
  5. __STDC__: 如果编译器遵循ANSI C标准,那么它的值就是1。
  6. __FUNCTION__: 它表示当前函数的名称。
#include <stdio.h>

int main() {
    printf("File: %s\n", __FILE__);
    printf("Line: %d\n", __LINE__);
    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);

    #ifdef __STDC__
        printf("This is a ANSI C compiler\n");
    #else
        printf("This is not a ANSI C compiler\n");
    #endif

    printf("Function: %s\n", __FUNCTION__);

    return 0;
}

   这段代码会打印出当前源文件的名称、行号、编译日期、编译时间、是否为ANSI C编译器,以及当前所在的函数。

注意:__FUNCTION__ 是C99标准引入的,如果你的编译器不支持C99,那么你将无法使用这个预定义符号。

(2)define定义常量

        语法:#define name stuff

#define MAX 100
#define reg register

注:语句后不加;(分号)

 (3)define定义宏

   #define机制包括一个规定,允许把参数替换到文本中,通过这种实现统称为宏定义

语法

#define name(parament_list) stuff

   :parament_list为参数列表,参数列表左括号必须与name紧邻

           宏参数是完全替换,用于求值时可能会出现运算等级问题,所以宏定义要多加括

           例如:

#define DOUBLE(x) ((x)+(x))

           带有副作用的宏参数尽量不用:x++ 

(4)宏规则及其特点

  •  #define定义中可以出现其他#define定义的符号
  • 宏中不能出现递归
  • 宏的参数是无关类型的
  • 执行速度快
  • 没法调试
  • 容易出现操作符优先问题

      所以进行一些简单操作运算时可以使用宏

(5)操作符#和##

  1. #

     #将宏的一个参数转换成字符串字面量(字符串化),仅允许出现在宏替换列表

#define PRINT(n) printf("the value of"#n"is"%d",n)
//预处理为:
                 printf("the value of a is "%d",a)

   2.## 

    ## 可以把位于两边的符号生成一个符号,连接必须产生一个合法标识符,否则是未定义的

(6)命名约定

    宏全大写,函数名不全都大写

(7)#undef

     用于移除一个宏定义

#undef name

(8)条件编译

       在编译一个程序的时候将一条语句 (一组语句) 编译或放弃。

       当满足条件时再继续编译

  • #if  //常量表达式
           为真存在,为假注释掉
       //...
    #endif

    注:不能为变量,因为变量在程序运行时才产生,此为翻译条件

  • 多分支
    #if  常量表达式
         //...
    #elif 常量表达式
         //...
    #else
         //...
    #endif
  •  判断是否被定义
    #if defined(symbol)
    #ifdef symbol
     
    #if !defined(symbol)
    #ifndef symbol
  • 嵌套指令

2.2编译

  编译过程就是将预处理后的⽂件进⾏⼀系列的:词法分析、语法分析、语义分析及优化,⽣成相应的 汇编代码⽂件。 

  编译后,C语言代码被翻译成了汇编代码。
汇编将汇编指令译成了二进制的指令。 

2.3汇编

  汇编器是将汇编代码转转变成机器可执⾏的指令,每⼀个汇编语句⼏乎都对应⼀条机器指令。就是根 据汇编指令和机器指令的对照表⼀⼀的进⾏翻译,也不做指令优化。

3.链接

  链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执⾏程序。 链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。 链接解决的是⼀个项⽬中多⽂件、多模块之间互相调⽤的问题。

每个源⽂件都是单独经过编译器处理⽣成对应的⽬标⽂件。

test.c 经过编译器处理⽣成test.o

add.c 经过编译器处理⽣成add.o 

4.运行环境

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值