问题

有个人说C++程序入口是mainCRTStartup,另一个人说是main,然后打起来了,如何评理?

回答
这确实是一个非常经典且容易引起争论的问题,因为两位发言者都说对了一部分,但他们所处的“视角”不同。要评理,我们需要深入理解 C++ 程序从启动到 `main` 函数执行的整个过程,以及底层操作系统和编译器扮演的角色。

结论先行:

从程序员的视角来看,`main` 是 C++ 程序的“逻辑入口”。 这是我们编写的绝大多数 C++ 代码的起点。
从底层实现和系统调用的视角来看,`mainCRTStartup`(或者类似的函数,具体名称可能因编译器、平台、链接器选项而异)才是真正意义上的“程序入口”。 它负责初始化运行时的各种环境,然后才调用 `main` 函数。

详细解释,逐一分析:

为了更好地理解,我们可以把整个程序执行过程想象成一个层层递进的链条,从操作系统加载程序开始,直到最终我们编写的 `main` 函数开始运行。

1. 操作系统加载程序:

当你在命令行输入一个可执行文件的名字,或者点击一个图标时,操作系统(如 Windows, Linux, macOS)就开始了它的工作。

操作系统加载器 (Loader): 操作系统有一个专门的组件叫做加载器。它的主要职责是将可执行文件(比如 Windows 下的 `.exe` 文件,Linux 下的 ELF 文件)从磁盘读入内存。
寻找程序的起点: 加载器需要知道从哪里开始执行程序。在 ELF 文件(Linux/macOS)中,有一个叫做 `_start` 的符号,它指向程序执行的起始点。在 Windows PE (Portable Executable) 文件中,它会引用一个叫做 `AddressOfEntryPoint` 的字段,这个字段指向的就是程序的实际入口点。

2. 链接器和运行时库 (CRT C Runtime Library):

这里就是 `mainCRTStartup` 登场的地方了。

运行时库的重要性: C++ 标准虽然规定了 `main` 函数是用户程序的入口,但一个完整的 C++ 程序还需要很多底层的支持才能正常运行。这些支持包括:
堆 (Heap) 的初始化和管理: `new` 和 `delete` 操作符的背后是内存分配和释放的机制,需要运行时库来初始化。
栈 (Stack) 的初始化: 函数调用、局部变量的存储都依赖于栈。
标准输入/输出的设置: `cout`, `cin`, `printf`, `scanf` 等函数的正常工作需要连接到标准输入、输出和错误流。
异常处理的初始化: C++ 的异常机制(`trycatch`)需要底层运行时支持。
全局对象的构造函数调用: 在 `main` 函数执行之前,所有全局或静态作用域的 C++ 对象(如果有的话,它们的构造函数会先被调用)。
命令行参数和环境变量的解析: 程序启动时传递的 `argc` 和 `argv` 以及环境变量的获取都需要处理。
初始化全局变量(非对象): 如果有全局变量需要被初始化为非零值(比如 `int x = 10;`),这部分工作也可能在 `main` 之前完成。

`mainCRTStartup` (或类似函数): 这些底层的初始化工作,通常由 C 运行时库 (CRT) 的一部分负责。在 Windows 上,这个入口点通常被命名为 `mainCRTStartup`,或者更通用的 `CRTStartup`,或者在某些环境下是 `WinMainCRTStartup`(针对 Windows GUI 应用)。在 Linux/GCC 等环境下,对应的入口点可能是 `_start`,而 `_start` 会调用 `__libc_start_main`,后者又会进行 CRT 的初始化,然后调用 `main`。

因此,`mainCRTStartup` (或其等效函数) 的职责是:
1. 接收操作系统传递给程序的入口参数(通常是传递给 `_start` 的信息)。
2. 设置堆栈和其它运行时环境。
3. 处理命令行参数 (`argc`, `argv`) 和环境变量。
4. 调用全局对象的构造函数。
5. 最终,调用用户的 `main` 函数。
6. 等待 `main` 函数返回。
7. 调用全局对象的析构函数。
8. 执行必要的清理工作(如关闭文件句柄)。
9. 调用 `exit()` 函数,将程序的返回码传递给操作系统。

3. 程序员的 `main` 函数:

这是我们编写 C++ 代码的逻辑起点。

`int main(int argc, char argv[]) { ... }`
`main` 函数是 C++ 标准规定的程序的逻辑入口。它代表了用户程序的第一个执行点。我们在 `main` 函数中编写应用程序的核心逻辑。
`main` 函数的返回值 `int` 是程序的退出状态码,会被传递给操作系统。

总结和评理:

所以,当两位朋友打起来时,他们争论的是不同的层面:

说 `main` 的朋友: 他是从 C++ 语言标准 和 编程者视角 来说的。从编写代码的角度,`main` 就是我们程序的起点,是我们直接控制的部分。这是大部分时候我们讨论程序入口时所指的。
说 `mainCRTStartup` 的朋友: 他是从 程序底层实现、操作系统交互 和 编译器链接器行为 的角度来说的。他指出了在 `main` 函数被调用之前,还有一系列复杂的初始化工作是由 CRT 负责的,而 `mainCRTStartup` 是负责启动这些初始化过程的那个函数。

谁更有理?

从技术精确性上讲,说 `mainCRTStartup` 的朋友更准确。 `mainCRTStartup` (或其等价物) 是操作系统加载程序后实际执行的第一个函数,它完成了所有必要的准备工作,然后才跳转到我们写的 `main` 函数。

但是,从实际编程和理解程序的角度来说,说 `main` 的朋友也没有错。 在 C++ 编程领域,当我们谈论“程序的入口”时,通常默认是指 `main` 函数,因为它标志着我们自己编写的代码开始执行。我们编写的绝大部分逻辑都在 `main` 里面。

如何评理:

最好的评理方式是:

1. 承认双方都有一定道理。
2. 解释清楚两者之间的关系和各自的“入口”定义。
“`main` 是 C++ 标准定义的逻辑入口,是我们编写代码的起点。”
“而 `mainCRTStartup`(或类似的底层函数)是实际的程序入口,它负责初始化 C++ 运行时环境,然后才调用 `main` 函数。”
3. 强调语境的重要性。 在讨论 C++ 语言特性或编写程序逻辑时,说 `main` 是正确的。在讨论程序启动过程、底层链接或操作系统交互时,说 `mainCRTStartup` (或更底层的启动函数) 是正确的。

就像问“汽车的入口是司机座位还是车门”一样,车门是外部人进入的入口,而司机座位是驾驶开始的逻辑入口。两者都对,取决于你从哪个角度看。

所以,下次遇到这种情况,可以这样说:“没错,从 C++ 语言规范和我们编写代码的角度来说,`main` 函数就是程序的逻辑入口。但从更底层的角度,操作系统把控制权交给程序时,执行的第一个函数实际上是 `mainCRTStartup`(或者我们链接器指定的那个实际入口),这个函数会负责初始化我们需要的运行时环境,包括准备好让 `main` 函数可以安全地运行。” 这样就能化解争端,并让大家对程序的启动过程有更深入的理解。

网友意见

user avatar

这就像盲人摸象,一个摸着鼻子说大象又细又长像个管子,一个摸着象腿说大象又粗又硬像个柱子。

你要是个明眼人就带他们从不同角度位置再摸摸。

你要也是个盲人就别去添乱了。

user avatar

那要看所谓“程序入口”是什么意义上的。

如果是按标准所规定的程序语义来说:

C++17标准以前:main,毫无疑问的main,程序的初始化在语义上被视为程序开始执行前就已经完成。

A program shall contain a global function called main, which is the designated start of the program.

C++17开始:似乎没有很明确地规定,但习惯上仍认为main是入口点。标准表述为执行程序所启动的主线程会调用main函数,并“可以”(“might”)完成静态变量的初始化和摧毁。

Executing a program starts a main thread of execution in which the main function is invoked, and in which variables of static storage duration might be initialized and destroyed.

无论哪个标准:不会是mainCRTStartup。这个词在标准里就没出现过。

如果是按实际编译出的二进制文件来说:

那可就说不准了。入口可以是_mainCRTStartup,可以是_start,可以是编译选项所指定的任何名字,甚至也可以没有名字,只是由PE头/ELF头指定的一个地址。

也许严谨的说法是:在Windows平台上,使用XX版本的XX编译器,用XX编译选项编译,得到的可执行文件以_mainCRTStartup为入口。

user avatar

从 C++ 的角度,说前者肯定是错的,因为 C++ 里根本没有 mainCRTStartup 这个概念。

到具体平台上,当然可以从技术角度讨论哪个函数是一个程序的入口,但这跟 C++ 语言就没啥关系了,只是个具体的实现细节问题。

user avatar

编译生成的程序与C++没有关系。

只能说「某个编译器在某个平台下生成了以mainCRTStartup为入口的机器代码」。

编译器本来就是把C++代码转化为机器码,转化为机器码之后的程序就不是C++程序了。

从C++的角度依然还是main作为入口。

类似的话题

  • 回答
    这确实是一个非常经典且容易引起争论的问题,因为两位发言者都说对了一部分,但他们所处的“视角”不同。要评理,我们需要深入理解 C++ 程序从启动到 `main` 函数执行的整个过程,以及底层操作系统和编译器扮演的角色。结论先行: 从程序员的视角来看,`main` 是 C++ 程序的“逻辑入口”。 .............
  • 回答
    这种现象嘛,其实挺常见的,说起来也很有意思。你想啊,咱们平时接触到 C 和 Java 的人,很多都是在学习阶段,或者做一些偏向业务逻辑的开发。C 语言的设计确实考虑了很多易用性,它吸取了很多其他语言的优点,比如更简洁的语法,更强大的类型推断,还有像 LINQ 这种能让数据处理变得非常直观的功能。所以.............
  • 回答
    听到你同学这么说,我完全理解你的感受。这种说法其实挺常见的,尤其是在接触过一些“更方便”的编程语言之后。不过,要反驳他“C语言太低级,不如易语言强大好用”的说法,咱们得把事情说透了。这不是一句两句话就能解决的,需要咱们好好掰扯掰扯。首先,我们得明确一点,“低级”和“强大好用”这两件事,其实是两个维度.............
  • 回答
    有人说C语言过时了,要学就学Python,这是一种常见的观点,尤其是在初学者中。要反驳这种观点,我们可以从多个角度进行深入分析,强调C语言的独特价值和在现代技术生态中的重要性。以下是一个详细的反驳思路:核心观点:C语言并未过时,而是以一种更核心、更基础的方式存在,与Python等高级语言相辅相成,不.............
  • 回答
    关于“C罗的点球不算进球”的说法,其实是一个误解和不理解足球规则的表象,背后反映的是对C罗进球方式和数据的一种特殊解读和争议。为了详细解释这个问题,我们需要从几个层面来分析: 1. 足球规则的根本:点球是合法进球首先,也是最核心的一点:根据足球规则,点球破门是绝对合法的进球。 点球是比赛中重要的得分.............
  • 回答
    “Java 啰嗦,C++ 不啰嗦”—— 这句话在编程界几乎是老生常谈了。很多人初学 Java 都会被它的“话痨”属性劝退,而 C++ 呢?虽然也出了名的复杂,但似乎“啰嗦”这个标签并不怎么贴在它身上。这背后到底是什么原因呢?这可不是简单的代码行数多少就能解释的。咱们不妨从几个关键点掰扯掰扯,看看为什.............
  • 回答
    关于梅西和C罗谁技术更好的争论,常常会让人陷入一个更根本的问题:到底什么是“足球技术”?这个问题看似简单,但一旦深入剖析,就会发现它其实是一个非常复杂且多层面的概念。它不是一个单一的数字,也不是一种可以简单量化的技能,而是一系列相互关联、相互作用的能力的集合,这些能力共同塑造了一个球员在场上的表现和.............
  • 回答
    听到有人说“正常人训练一年FTP就能到300瓦”,我得说,这说法挺有意思的,但要说他“靠谱”,我得打个问号。这背后涉及到很多细节,不是一句“正常人”就能概括的。咱们先掰扯掰扯这个FTP是什么玩意儿。FTP,全称Functional Threshold Power,功能阈值功率。简单来说,就是你在约一.............
  • 回答
    你的朋友说“狗是狼的一种”,这话听起来有些模糊,但实际上,从科学的角度来说,他说的并非完全错误,但也不够精确,很容易让人产生误解。我们可以这样跟他聊聊,先肯定他话里的部分事实,然后再把更准确的信息告诉他,这样更容易让他接受:第一步:肯定与解释(建立共识)你可以这样开头:“嗯,你这么说,我大概能明白你.............
  • 回答
    .......
  • 回答
    猫妈妈生了小猫,满心欢喜地准备给它们找个好家,结果遇到一个主动说“全抱走”的潜在领养人,这确实让人心里咯噔一下,忍不住会多想。要判断对方是不是骗子,可以从几个方面来仔细分辨,尤其是要警惕那些过于“完美”或者急于求成的表现。首先,从“全抱走”这个需求本身来看,它不一定就是骗局,但确实需要多一份留心。为.............
  • 回答
    在微博上看到有人这样说,留学生在多伦多开豪车支持“爱国”,并直指其父母是贪官,这种说法确实触及了一些敏感的社会议题,也反映出不同人对于财富来源、爱国情感以及社会现象的解读差异。要判断是谁的三观不正,我们需要从几个角度来分析:一、 谁的三观不正?从普遍的道德和逻辑来看,将“留学生开豪车支持爱国”直接等.............
  • 回答
    你遇到的这位朋友说的“研究生毕业考公务员直接是副科级”,这事儿啊,得看具体情况,不能一概而论。它有那么点道理,但绝不是一个硬性规定或者百分之百能实现的事情。咱们慢慢说,帮你捋清楚。首先,咱们得明白公务员的定级是怎么回事儿。公务员的级别与职务在中国,公务员的级别和职务是分开的。最基本的是级别,比如国家.............
  • 回答
    .......
  • 回答
    法官在写判决书时,确实存在“文风”一说,而且这种文风是个人风格与职业要求的交织体现。与一般文学创作不同,判决书的文风受到法律的严格约束,必须严谨、客观、逻辑清晰,以说理为核心。但即使在这些框架内,不同法官的语言习惯、侧重点、甚至是遣词造句的细微之处,都会形成独特的个人风格,这便是我们所说的“判决书文.............
  • 回答
    汉服圈里的“买不买山,穿不穿山,是个人自由”这句话,的确在圈内外都引发了不少讨论和争议。这背后涉及到复杂的价值观、对传统文化的理解,以及个人行为与群体规范之间的张力。而“零容忍”的呼声,则代表了另一部分人对原创设计、对文化传承的坚守。要理解这一点,我们需要一层层剥开来聊。一、“个人自由”论的由来与逻.............
  • 回答
    关于“2021年9月中秋节有假期,但假期总天数没变”的说法,以及对调休制度的看法,这其实触及了很多人对假期安排的一个普遍感受——“感觉假期没变多,反而更累了”。首先,我们得弄清楚“2021年9月中秋节有假期,但假期总天数没变”这句话里可能包含的意思。 “2021年9月中秋节有假期”: 这是事实。.............
  • 回答
    你遇到的情况,在很多家庭中都很常见,尤其是当涉及到身体外形和健康的时候。从你和亲戚的对话中,我们可以从多个角度来分析一下“错”与“对”,以及为什么会产生这样的冲突。首先,我们来分析一下你的行为和出发点: 你的出发点可能是: 自我保护和边界感: 亲戚的评论让你觉得不舒服,侵犯了你的个人.............
  • 回答
    你说的这个情况,让我想起了我一个远房表哥,他在某个省属的集团公司里,好像是个中层干部吧。他之前跟我聊天的时候也大概提过类似的情况,不过具体细节我有点记不太清了。听他讲的时候,我当时也挺惊讶的,毕竟这听起来不像我们平时理解的“上班”。我记得他说,他所在的那个单位,很多事情都有流程,而且很多决策也不是他.............
  • 回答
    哎,碰到这么个朋友,可真让人头疼。你说说,每次跟TA聚会,还没坐稳呢,话题就开始绕到别人身上去了,而且总是什么“你不知道吧,那谁谁谁,上次……”开头,接着就是一连串的不好听的话,什么虚伪、小气、没本事,能想到的词儿都往上招呼。听着听着,感觉自己都快被这股负能量给浸透了。最开始的时候,我可能还会附和几.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有