【维生素C语言】第十八章 - C语言程序环境

简介: 程序环境是什么?我们都 "经历" 过,但不曾感知到 "他" 的存在。我们其实在不知不觉中早就已经接触到了程序环境…… 第一次创建了一个文件(test.c),敲下那句 "hello world" 随后保存后点击运行后编译出可执行文件(test.exe)时,其实就已经接触到了 "他" 了。

前言


程序环境是什么?我们都 "经历" 过,但不曾感知到 "他" 的存在。我们其实在不知不觉中早就已经接触到了程序环境…… 第一次创建了一个文件(test.c),敲下那句 "hello world"  随后保存后点击运行后编译出可执行文件(test.exe)时,其实就已经接触到了 "他" 了。


我们只是按下了运行,然后好像所有东西都像变魔术一样直接就产生了,这一切都似乎是理所当然的事。但是你是否思考过他是如何变成 "可执行程序" 的呢?在这一章,我们将简单地探讨一个 "源程序"是如何变成 "可执行程序" 的,作一个大概了解。

一、翻译环境和执行环境


0x00 ANSI C 标准

ANSI C是由美国国家标准协会(ANSI)及国际化标准组织(ISO)推出的关于C语言的标准。ANSI C 主要标准化了现存的实现, 同时增加了一些来自 C++ 的内容 (主要是函数原型) 并支持多国字符集 (包括备受争议的三字符序列)。


📚 ANSI C 几乎被所有广泛使用的编译器所支持,且多数C代码是在ANSI C基础上写的。


🔍 【百度百科】ANCI C 标准


0x01 程序的翻译环境和执行环境

📚 ANSI C 的任何一种实现中,存在两种不同的环境:


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


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

e3552cb21ebf358a4abf9ac88c83dc4a_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16.png

二、详解编译和链接


0x00 翻译环境

e745446121dfbb4a0ebcf8f51cbb7207_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_35,color_FFFFFF,t_70,g_se,x_16.png


📚 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)


每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。


连接器同时也会引入标准C库函数中任何被该程序所用到的函数,且可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。


💬 举个例子:test.c、add.c、minu.c

77e1e4b40fc8b9446329512287332830_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16.png



0x01 编译本身的几个阶段

💬 举个例子:


① sum.c


int global_val = 2021;
void print(const char* string) {
    printf("%s\n", string);
}

② test.c


#include <stdio.h>
int main(void) {
    extern void print(char* string);
    extern int global_val;
    printf("%d\n", global_val);
    printf("Hello,World!\n");
    return 0;
}



test.c

sum.c

预编译截断(*.i

预处理指令

……

编译(*.s

语法分析

词法分析

语义分析

符号汇总

           

汇编(生成可重定位目标文件 *.O

形成符号表

汇编指令 → 二进制指令 ----test.o

链接

1. 合并段表

2. 符号表的合并和符号表的重定位

隔离编译,一起链接。

1. 合并段表


2. 符号表的合并和符号表的重定位


隔离编译,一起链接。


📚 main.c


extern int sum(int, int);
int main(void) {
    sum(1, 2);
    return 0;
}

📚 sum.c


int sum(int num1, int num2) {
    return( num1 + num2);
}

🔑 解析图(VS2019):

684bb9116df4da6e9ef2eb4593e2d354_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16.png


0x02 运行环境

📚 程序执行过程:


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


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


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


④ 终止程序。正常终止 main 函数(也有可能是意外终止)。


💬 举个例子:这段代码的执行过程

int Add(int x, int y) {
    return( x + y);
}
int main(void) {
    int a = 10;
    int b = 20;
    int ret = Add(a, b);
    return 0;
}

194ca1e2fa44ff1d933160a0550c0bae_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5Yaw5qON6KKL5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16.png


📚 这里还有一个概念:函数栈帧 (目前做简单了解,后续我将专门写一篇函数栈帧的讲解)

【百度百科】C语言中,每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。

相关文章
|
2月前
|
存储 自然语言处理 编译器
【C语言】编译与链接:深入理解程序构建过程
【C语言】编译与链接:深入理解程序构建过程
|
13天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
32 5
|
4月前
|
编译器 C语言 计算机视觉
C语言实现的图像处理程序
C语言实现的图像处理程序
175 0
|
13天前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
45 4
|
12天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
36 1
|
13天前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
23 2
|
13天前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
29 1
|
2月前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序
|
3月前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
113 10
|
2月前
|
Linux C语言 iOS开发
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
28 0