C语言程序一定要从main函数开始执行吗?很多高手都搞不清楚

在GNU C语言中,程序的入口点通常被认为是main函数。然而,通过使用诸如链接脚本、启动代码和ld命令中的-e参数等多种方式却可以实现改变程序的入口。本文将通过具体的C语言代码示例和相关技术手段,深入研究GNU C语言中程序执行流程的灵活性。本文展现是思考的过程,通过这种方式希望能让读者一通百通,授之以渔,一定要读完!后续持续C语言高级系列文章,欢迎关注、点赞、收藏。

示意图(可忽略)

C语言的灵活性使得我们能够在程序的执行过程中进行精细的控制。虽然main函数通常被认为是程序的入口点,但我们可以通过调整链接脚本、启动代码,甚至使用ld命令的一些特殊参数,改变程序的执行流程。

在上述代码中,main函数被认为是程序的起始点。但我们可以通过一些技术手段来改变这一默认行为。

上述代码中,通过自定义链接脚本 custom_linker_script.lds,我们将程序的入口点设置为 my_entry 函数,而不再是 main 函数。在编译链接时,我们可以使用以下命令:

在这个例子中,我们使用了一个名为 _start 的函数作为程序的入口点。启动代码会负责在程序启动时调用 _start 函数。编译链接时,可以使用以下命令:

使用 ld 命令的 -e 参数可以直接指定程序的入口点。编译链接时,可以使用以下命令:

理解为何使用链接脚本、启动代码以及ld命令的 -e 参数等方式能够改变程序的入口点需要深入了解C程序编译和链接的过程,以及操作系统加载可执行文件的机制。

  1. 编译阶段

在编译阶段,源代码(.c 文件)被编译成目标文件(.o 文件)。这个阶段主要包括预处理、编译和汇编。

  1. 链接阶段

在链接阶段,目标文件被链接成可执行文件。这个过程包括解析符号、地址空间分配、重定位等步骤。链接器(ld命令)负责将多个目标文件组合成一个可执行文件。

链接器作用

在默认情况下,链接器会将程序的入口点(即程序启动时首先执行的地方)设置为一个特定的符号,通常是_start。这是一个预定义的入口点,由启动文件(crt0)提供。启动文件执行一些基本的初始化工作,然后调用C运行时库的初始化函数,最终跳转到main函数。

GCC 程序启动流程

  1. 链接脚本

链接脚本定义了可执行文件在内存中的布局和组织方式,包括程序的入口点。通过在链接脚本中使用 ENTRY 命令,我们可以显式地指定程序的入口点。这就是为什么链接脚本能够改变程序的入口点的原因。

  1. 启动代码

启动代码是在程序启动时执行的一段特殊代码。通过自定义启动代码,我们可以在程序启动时执行自己的初始化逻辑,然后选择跳转到任意的函数作为程序的入口点,而不仅仅是默认的_start。这就是为什么启动代码能够改变程序的入口点的原因。

  1. ld命令的 -e 参数

-e 参数直接指定程序的入口点。通过这个参数,我们可以告诉链接器在哪里开始执行程序。这就是为什么使用ld命令的 -e 参数能够改变程序的入口点的原因。

通过链接脚本、启动代码以及ld命令的 -e 参数等方式,程序员可以在编译和链接的过程中插入自定义的逻辑,从而控制程序的启动过程。这些方法提供了对程序启动流程的灵活性,使得程序员能够更精细地控制程序的行为和执行流程。

第1节:初识C语言

C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的。C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现。

  • 易于学习。
  • 结构化语言。
  • 它产生高效率的程序。
  • 它可以处理底层的活动。
  • 它可以在多种计算机平台上编译。

C 语言最初是用于系统开发工作,特别是组成操作系统的程序。由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。下面列举几个使用 C 的实例:

  • 操作系统
  • 语言编译器
  • 汇编器
  • 文本编辑器
  • 后台打印服务(Print Spooler)
  • 网络驱动器
  • 现代程序
  • 数据库
  • 语言解释器
  • 实体工具
  • 服务器。
  • 操作系统。
  • 上层应⽤。 MFC、QT
  • 嵌⼊式。
  • ⼈⼯智能、硬件驱动。
  • 中间件。
  • ⽹络攻防、数据安全。
  • ⼤学必修课。
  • 名企、外企。

如果你希望使用计算机做某些事,就必须为其提供特殊的指令列表(程序),确切地告诉计算机要做的事以及如何做。 1.4 使用C语言的七个步骤

  • 定义程序的目标
  • 设计程序
  • 编写代码
  • 编译
  • 运行程序
  • 测试和调试程序
  • 维护和修改程序
  • C语言代码
    • 头文件.h
    • 源文件.c

C 语言有没有字符串类型?

为什么出现这种类型?

每种类型的大小是多少?

课后知识学习部分

1.对编程而言,可移植性意味着什么?

2.解释源代码文件、目标代码文件和可执行文件有什么区别?

3.编程的7个主要步骤是什么?

4.编译器的任务是什么?

5.链接器的任务是什么?

C PrimerPlus 引导实例

你刚被MacroMuscle有限公司聘用。该公司准备进入欧洲市场,需要一个把英寸单位转换为厘米单位(1英寸=2.54厘米)的程序。该程序要提示用户输入英寸值。你的任务是定义程序目标和设计程序(编程过程的第1步和第2步)。

  • 第一步:提示用户输入英寸值(scanf)
  • 第二步:英寸单位转换为厘米(浮点型float 整型int)
  • 第三步:英寸 = 2.54厘米 centimeter=inch*2.54

用JAVA代码解决上述问题:补充知识点Scanner类的使用

用python代码解决上述问题:补充知识点:强制类型的转换

  • Windows操作系统
  • vs(visual studio)2013、2015、2017、2019、2022
  • Clion:跨平台IDE、跟Java的IDEA、python的pycharm是同一家公司的
  • Qt Creator 跨平台IDE
  • MacOS(苹果电脑的操作系统)
  • Xcode Clion:跨平台IDE。 Qt Creator 跨平台IDE。
  • Linux:
  • vi/vim —— ⽂本编辑器。 Clion:跨平台IDE。 Qt Creator 跨平台IDE。 备注:大多企业开发用vs会更多一些
  1. 打开微软的官方网站 https://visualstudio.microsoft.com/,下载 Visual Studio 安装包。
  1. 双击安装包进行安装
  • 操作一:在 “工作负荷” 标签页中,选择 “使用 C++的桌面开发” 选项即可。
  • 操作二:“安装位置” 中修改安装路径。

路径的要求: </br> 1、不要有中文,不要有空格,不要有一些特殊符号</br> 2、选择一个统一的文件夹进行管理

  1. 自动下载并安装,过程略微漫长,耐心等待。
  1. 安装完成,弹出 “安装完毕” 对话框。 点击确定。
  1. 接下来,VS希望你使用微软的账号登录,没有可以注册一个。也可以点击“暂时跳过此项”。
  1. 根据提示选择一个自己喜欢的主题
  1. 点击启动,到此整个环境全部搭建完毕
  1. 创建项目 点击 “创建新项目”,创建一个项目。
  1. 选择创建 “控制台应用”,点击下一步。
  1. 指定项目名称。确保位置下的项目存储目录存在。 勾选 “将解决方案和项目…..” ,点击 “创建”。
  1. 右侧的解决方案管理器可以按照自己的习惯是放在左侧或者右侧默认是右侧,可以拖到左侧来,每个人的习惯不同,没有固定标准
  1. 创建 helloworld.c ⽂件 右键选择原文件,选择添加,选择新建项
  1. 在弹出的编辑框中,选中 “C++文件(.cpp)”,将 下方 “源.cpp” 手动改为要新创建的文件名, 如:helloWorld.c 。注意,默认 cpp 后缀名,要手动改为 .c 后缀名,然后点击 “添加”。
  1. 编写 helloworld.c程序。
  1. 点击上方绿色空心三角运行即可
  1. #include: 引⼊头⽂件专⽤关键字。
  2. <> : ⽤来包裹 库头⽂件名
  3. stdio.h : 使⽤的头⽂件。因为程序中使⽤了 printf() 函数。就必须使⽤该头⽂件。

std:标准:standard </br> i: input 输⼊。</br> o: output 输出。</br>

  1. int :main 函数返回值为整型。
  2. main: 整个程序的⼊⼝函数。 任何.c 程序,有且只有⼀个 main 函数。
  3. printf(); C语⾔向屏幕输出字符使⽤的函数。
  4. printf(“helloworld\\n”) printf();向屏幕输出一段内容 helloworld: 待写出的字符串内容。 \\n: 回⻋换⾏。
  5. return 0; return 返回。 C程序要求,main 函数要有返回值。借助 return 实现返回。 0:成功!因为 int ,返回整数。 注意事项
  • 程序中使⽤的所有的字符,全部是 “英⽂半⻆” 字符。
  • 程序中,严格区分⼤⼩写。
  • “;” 代表⼀⾏结束。不能使⽤ 中⽂ “;”,必须是英⽂。

完成的C语言运行,分为以下4步,在VS中我们直接运行,其实是把中间的步骤给省略了

  • 预处理(这一步后面单独讲解)
  • 简单理解,就是先找到#include后面的 <stdio.h>这个文件
  • 编译
  • 把c文件编译成二进制文件后缀名为obj
  • 连接/链接
  • 把预处理找到的h文件,还有编译之后产生的obj文件打包在一起,产生exe文件
  • 运行
  • 运行exe文件

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。