C语言程序从源码到运行(进阶篇)

1.预处理过程

预处理命令一般以#开头,包括以下几个

头文件包含:#include.
定义一个宏:#define
条件编译:#if、#else、#endif.
编译控制:#pragma

预处理过程就是处理这些命令:

头文件展开:将#include包含的头文件内容展开到当前位置。
宏展开:展开所有的宏定义,并删除#define.
条件编译:根据宏定义条件,选择要参与编译的分支代码,其余的分支丢弃。
删除注释。
添加行号和文件名标识:编译过程中根据需要可以显示这些信息。
保留 # pragma命令:该命令会在程序编译时指示编译器执行一些特定行为。

1.c的代码如下

#include"1.h"
#define N 10
int main(){
        test();
//测试
#pragma pack(2)
#pragma message("build main.c...\n");
        int a=N;
        return 0;
}

 1.h代码

void test(){
        #ifdef ARM
                printf("ARM platform init...\n");
        #else
                printf("X86 platform init...\n");
        #endif
}

 生成1.i文件如下

 gcc -E 1.c -o 1.i

# 0 "1.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "1.c"
# 1 "1.h" 1
void test(){



  printf("X86 platform init...\n");

}
# 2 "1.c" 2

int main(){
 test();

#pragma pack(2)

# 7 "1.c"
#pragma message("build main.c...\n");
 int a=10;
 return 0;
}

预处理前后文件的变化对比

#include将包含的头文件的内容展开

//删除注释;

#define直接文本替换。

#ifdef 根据开发者定义的宏标记,选择要参与编译的代码部分,其余部分删除

#pragma保留

2.编译过程

编译过程可以分为以下6步。


(1)词法分析。

        编写程序时,不小心输入了中文符号、圆角/半角字符导致编译出错,发生在这个阶段。


(2)语法分析。

        语法分析工具在对token序列分析过程中,如果发现不能构建语法上正确的语句或表达式,就会报语法错误:syntaxerror。如果程序语句后面少了一个语句结束符分号或者在for循环中少了一个分号,报的错误都属于这种语法错误。


(3)语义分析。

        语法分析仅仅对程序做语法检查,对程序、语句的真正意义并不了解,而语义分析主要对语法分析输出的各种表达式、语句进行检查,看看有没有错误。如果传递给函数的实参与函数声明的形参类型不匹配或者使用了一个未声明的变量,或者除数为零了,break在循环语句或switch语句之外出现了,或者在循环语句之外发现了continue语句,一般都会报语义上的错误或警告。

(4)中间代码生成

        中间代码和语法树相比,有很多优点:中间代码是一维线性序列结构,类似伪代码,编译器很容易将中间代码翻译成目标代码。

(5)目标代码生成。


(6)目标代码优化。

gcc -S 1.i -o 1.s 可以生成汇编代码,汇编代码如下:

      .file   "1.c"
        .text
        .section        .rodata
.LC0:
        .string "X86 platform init..."
        .text
        .globl  test
        .type   test, @function
test:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        leaq    .LC0(%rip), %rax
        movq    %rax, %rdi
        call    puts@PLT
        nop
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   test, .-test
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $0, %eax
        call    test
        movl    $10, -4(%rbp)
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long   1f - 0f
        .long   4f - 1f
        .long   5
0:
        .string "GNU"
                                  53,2-9        76%

1:
        .align 8
        .long   0xc0000002
        .long   3f - 2f
2:
        .long   0x3
3:
        .align 8
4:
                                  67,2          Bot

3.汇编过程

        gcc -c 1.s -o 1.o 是将源文件/.s汇编文件翻译成二进制文件

编译器在编译一个项目时,是以C源文件为单位进行编译的,每一个源文件经过编译,生成一个对应的目标文件。汇编器将汇编代码转变成机器可执行命令,每一个汇编语句都对应一条机器指令。

二进制文件都是机器码。

4.链接过程

汇编过程是使用汇编器将前一阶段生成的汇编文件翻译成目标文件

gcc 1.c -o a.out 可以生成可执行程序

c语言24点游戏源码 c语言Turbo C下写的俄罗斯方块 c语言UDP传输系统源码 c语言奔跑的火柴人游戏源码 c语言别踩白块儿(双人版)源码 C语言超市管理系统 c语言吃逗游戏源码 c语言打字母游戏源码 c语言打字游戏代码 c语言大丰收游戏源码 c语言地空对战游戏 c语言电子时钟程序 c语言对对碰游戏源码 c语言对自己电脑系统测试 c语言俄罗斯方块 c语言盒子接球游戏源码 c语言黑白棋ai游戏源码 c语言华容道源码 c语言火车票订票管理源码 c语言教工工资管理系统 c语言坑爹;大冒险 c语言矿井逃生 c语言力学相关的流体源码 c语言连连看游戏源码 c语言模拟快打旋风游戏源码 c语言配有图片和音乐的打字母游戏 c语言实现类似弹力球效果 c语言实现如果cmd中的ping c语言实现数字雨 c语言实现水波纹显示效果 c语言实现图片转化为ASCI图 c语言贪吃蛇游戏的双人对战版 c语言坦克游戏源代码 c语言通讯录管理系统源码 c语言图书管理系统源码 c语言图书借阅系统源码 c语言涂格子游戏源码 c语言万年历源码 c语言文本编辑器系统源码 c语言五子棋源码 c语言学生成绩管理系统 c语言学生成绩管理系统源码 c语言学生信息系统 c语言支持自2已创建迷宫,并求解最短路径 c语言种地要浇水游戏源码 c语言自创军旗游戏源码 c语言自创推箱子游戏改版 c语言做的播放器源码 c语言做的绘图板系统 c语言做的一个任务管理器 纯c语言迷宫源码 链表HuffmanTree
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值