我们现在有的,是一个hello.c文件,通过cl命令就可以生成目标hello.exe文件。

那我们就可以研究一下cl这个东西。

CL解释

CL.EXE(或cl.exe,似乎windows的文件系统对于大小写是不敏感的),是何许人也呢?

因为VC6的版本说明没有找到,这里的说明文字是Visual studio 2013的CL.EXE说明,不过都是一样的。

CL是用来控制微软C和C++编译器(compiler)和链接器(linker),一共做了两件事情。编译器会生成COFF文件格式的目标文件(.obj);链接器会生成可执行文件(.exe)或者动态链接库文件(DLLs)。

对比我们之前的做法,的确是执行cl命令之后,生成了一个hello.obj文件和一个hello.exe文件。

选项的使用

数了一下,有99个选项之多。每个选项都有自己的作用,就需要使用的时候去熟悉了,不过我们现在不需要了解这么多,我们就来看下/c选项好了。This option prevents the automatic call to LINK. Compiling with /c creates .obj files only. You must call LINK explicitly with the proper files and options to perform the linking phase of the build.

Any internal project created in the development environment uses the /c option by default.

To set this compiler option in the Visual Studio development environment

This option is not available from within the development environment.

To set this compiler option programmatically

This compiler option cannot be changed programmatically.

要彻底理解它,就必须知道C语言到目标代码的过程。

▓首先,C语言中有两种文件,一个.c文件(我们一般称之为源文件),一个.h文件(我们一般称之为头文件)。头文件一般会被源文件包含,而源文件会被编译成一个二进制中间文件,之后所有的二进制中间文件会通过链接器进行链接,形成一个可以在某个特定系统上执行的二进制可执行文件。

于是,C语言-->可执行代码可以明显的分为编译过程和链接过程,而由于C语言中一种特殊语法--“宏”的存在,所以还有一个预编译过程,在预编译过程中,C语言中的宏会被展开;同时,包含的头文件中的代码,会根据条件编译等,囊括到源文件中,这些工作做好后,给编译器的就是一份新的源码文件,供编译阶段使用。

另外,相信大家都知道,C语言是从汇编语言发展过来的,汇编是从机器码发展过来的,以前的编译器都是先将C语言编译成汇编语言,再将其解释成机器码就可以了。现代编译器除了做这个,还可以对代码进行优化。不过基本思想是一直没有变的。

而我们做C开发的时候,有时稍微看一下汇编之后的代码,对于计算机是如何执行程序的过程,会有更清晰的认识。

那么,用cl可以生成汇编代码吗?答案当然是肯定的。

在命令行输入cl /FA hello.c,看看生成了哪些东西?当然,如果你不要生成.exe文件,可以加上/c选项。

可以看到生成了.obj文件和.asm文件。

.asm的汇编代码,仅仅用cl再进行编译,我还没有找到方法,所以这里就要引入一个新工具--ml,ml是MASM中编译汇编代码使用的编译器,同样,它也会调用到link,并且让它不调用link,使用的编译选项也是/c。

从cl和hello.c,我们引出了hello.obj,hello.asm,以及ml.exe,包括C语言到可执行文件的过程。下面先跳过ml,来看看链接过程。

链接过程

链接过程也就是将.obj变成.exe的过程,使用的是link.exe。

直接使用cl /c hello.c产生的hello.obj文件,输入命令link hello.obj,直接就生成了.exe文件。

真简单~不过,且慢,我们有main函数,但是至少printf函数这个东西,是在哪里呢?

秘密就藏在生成的那个.obj文件中啦!如果用另外一个.obj文件(稍候我们会用另外一个hello.obj),那就会得到错误哦。

那我们打开obj文件来看看吧。怎么?还要看二进制文件?不用担心,看的还是英文字符,多说无用,还是看下就知道了。

这里我使用的是winhex,其实使用其他任何一个文本编辑器都是可以的,不过看二进制文件我还是习惯使用专门的二进制编辑器。截图用的picpick。顺便说明下。

左边是文件内容,主要看右边,红线划过的地方。看不清的同学可以看这里:-defaultlib:LIBC –defaultlib:OLDNAMES

其实,链接过程会将所有的静态库和目标文件进行链接,而在这份hello.obj文件中,指定了两个default lib,一个为libc.lib,一个为oldnames.lib。而这两个lib文件又是何方神圣呢?

libc.lib为单线程静态C标准库(在cl中可使用/ML选项定义对其的链接),而oldnames.lib则是为了兼容微软以前的C/C++开发系统,基本不使用了,至少在我们这个hello.c编译链接成exe的过程中,可以忽略掉它。

其实,我们用一个很简单的方法可以知道我们的程序链接了哪些库。d:\test>link /verbose:lib hello.obj

Microsoft (R) Incremental Linker Version 6.00.8168

Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Searching Libraries

Searching D:\Program Files\Microsoft Visual Studio\VC98\lib\LIBC.lib:

Searching D:\Program Files\Microsoft Visual Studio\VC98\lib\OLDNAMES.lib:

Searching D:\Program Files\Microsoft Platform SDK\Lib\.\kernel32.lib:

Done Searching Libraries

这里还可以使用一个小工具,叫做dumpbin的,可以利用它的选项来分析hello.obj文件,看到defaultlib,而不用打开文件自己查看。

——————————————

d:\test>dumpbin /DIRECTIVES hello.obj

Microsoft (R) COFF Binary File Dumper Version 6.00.81683 Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file hello.obj

File Type: COFF OBJECT

Linker Directives

-----------------

-defaultlib:LIBC

-defaultlib:OLDNAMES

Summary

A .data

26 .drectve

14 .text

——————————

oldnames.lib我们可以略过,但是libc.lib我们还是需要了解的,今后要做VC相关项目,使用到第三方库的会经常用到。为了解释libc.lib,我们需要引入一个新的概念--“C语言运行库”,这里我们只讨论windows平台,VC中使用的被称为MSVC CRT。

另外还要牵涉到的一个概念就是线程。

C语言运行时库(C Run-time Library)---CRT

要了解这个东西,就需要对C语言的发展史有一定的了解。C语言是在上世纪70年代在B语言的基础上被发明出来的,之后Dennis Ritchie 和 Brian Kernighan 就用C本身重写了90%以上的 UNIX 系统函数。并且把其中最常用的部分独立出来,形成头文件和对应的 LIBRARY,C run-time library 就是这样形成的。在类UNIX系统中,C运行库被认为是系统的一部分。

而随着C语言的流行,出现了很多C编译器,也就有很多C运行时库的实现。主要有下面的几种

BSD libc, implementations distributed under BSD operating systems.

◑GNU C Library, used in GNU/Linux and GNU/HURD.

◑Dinkum C99 Library from Dinkumware, most common commercially licensed one

◑Microsoft C Run-time Library, part of Microsoft Visual C++

◑dietlibc, an alternative small implementation of the C standard library (MMU-less)

◑uClibc, a C standard library for embedded Linux systems (MMU-less)

◑Newlib, a C standard library for embedded systems (MMU-less)

◑klibc, primarily for booting Linux systems.

◑EGLIBC, variant of glibc for embedded systems.

◑musl, another lightweight C standard library implementation for Linux systems

可以看到,我们现在讨论的Microsoft C Run-time Library也是其中的一种。在那个年代,线程还没有被应用到操作系统上,应用程序都是单线程的。所以最初的C Run-time Library都是单线程的。另外动态库的概念也是后期出现的,所以一开始C Run-time Library也只是静态链接。

随着时间的推移,计算机技术也在不断进步。C语言运行时库也根据单线程、多线程、静态链接、动态链接,是否需要debug信息的不同,分为不同的版本。在微软是MSVC CRT实现中,具体是按照表格中的实现来分类的。其中,静态链接有单线程和多线程版本,动态链接仅有多线程版本。

使用link链接CRT

前面我们的obj文件中就包含有default lib,那如果我们的obj文件中不包含该信息呢?

首先,我们需要生成一个不包含default lib信息的obj文件。

这里有两种方法,一种是生成ASM文件,然后利用ml来生成一个obj文件,其中不包含该信息(当然ml也会主动调用link,这里也需要使用选项来控制,具体有兴趣的童鞋可以自行研究,因为这里主要还是C/C++编程为主,汇编会涉及,但是不会深入);还有一种方法是利用cl的/Zl选项,这里要注意的是l是小写的L而不是I,我一开始就是看错了,结果编译出来还是带有default lib信息的。cl /c /Zl hello.c

之后利用dumpbin来查看一下是否生成正确。然后再调用link看看。

结果如下:

现在就找不到_printf和_mainCRTStartup这两个符号了。

之后使用link hello.obj libc.lib看看。

成功生成hello.exe!

总结

使用到的工具

★CL.EXE

★LINK.EXE

★ML.EXE

★DUMPBIN.EXE

★WINHEX

整个C程序编译过程, MSVC和GCC对比

VC文件后缀名

“我是一名从事了10年开发在退休边缘垂死挣扎的高龄程序员,最近我花了一些时间整理了一个完整的学习C语言、C++的路线,项目源码和工具☞C/C++编程项目开发学习视频,素材笔记,项目源码等,还有新鲜出炉的学生成绩管理系统 ~ 对于想学习C/C++的小伙伴而言,学习的氛围和志同道合的伙伴很重要,笔者强烈推荐主页的编程爱好者的聚集地!

欢迎初学和进阶中的小伙伴。希望你也能凭自己的努力,成为下一个优秀的程序员。工作需要、感兴趣、为了入行、转行需要学习C/C++的伙伴可以一起学习!”

关注我,带你遨游代码世界!

下面这些是C/C++能做的 :

服务器开发工程师、人工智能、云计算工程师、信息安全(白客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等!

crt是什么意思 windows编程_从零开始,学习windows编程 - hello.c的疑惑!相关推荐

  1. python重复元素判定编程_从零开始学Python编程四:条件判断与循环

    前面已经介绍了不少Python基础知识,大家不要觉得不耐烦,想要学好Python,做好Python开发,一定要打牢基础.大家也发现了,Python中很多基础知识和数学算法是一样的,比如今天要教给大家的 ...

  2. 好书推荐——从零开始学习 Julia 编程、数学和数据科学。

    好书推荐--数据科学简介:从零开始学习 Julia 编程.数学和数据科学. 书 好书推荐--数据科学简介:从零开始学习 Julia 编程.数学和数据科学. 书籍信息 前言 个人感受 封面: 个人感受 ...

  3. access 导入 txt sql语句_从零开始学习 MySQL 系列索引、视图、导入和导出

    阅读本文大概需要 8 分钟 前言上篇文章我们学习了数据库和数据表操作语句,今天我们学习下数据库索引,视图,导入和导出的知识.作为基础篇,不会涉及到关于索引和视图的高级应用和核心概念,但是基本操作大家会 ...

  4. mysql导入dat文件_从零开始学习 MySQL 系列--索引、视图、导入和导出

    前言 上篇文章我们学习了数据库和数据表操作语句,今天我们学习下数据库索引,视图,导入和导出的知识. 作为基础篇,不会涉及到关于索引和视图的高级应用和核心概念,但是基本操作大家会了解,尤其是关于索引的内 ...

  5. java编程学习方法_在线学习Java编程的最佳方法

    java编程学习方法 1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告 ,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好 ...

  6. python3从零开始学习_从零开始学习PYTHON3讲义(十五)让画面动起来

    <从零开始PYTHON3>第十五讲 虽然看起来绘图和音乐并不相关,但是听过了上一讲的内容你一定知道,这是游戏编程中四个需要处理内容的两部分,这两部分必须同时.并行的处理,不能因为某一项计算 ...

  7. windows镜像_什么是windows镜像?什么是Ghost?它们有什么优缺点?

    大家好,欢迎回到万魔寺,从本期开始,从零开始学习安装操windows的教程就开始了, 这期,首先分享的是--零基础扫盲知识. 原本这是系列视频教程,发布后有许多朋友非常喜欢,期间有朋友提出部分语速过快 ...

  8. java安装_在线学习Java编程的最佳方法

    java安装 1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好消息是,您 ...

  9. 学python编程_少儿学Python编程的一些思考

    自从孩子上了初中,孩子妈就开始盯着各种真假难辨的中考.高考新政传言.当她从铺天盖地的少儿编程广告里获悉,编程将纳入中考,高考范围,并且2018年高考,多个省份的数学卷甚至都出现了编程题时,就变得异常兴 ...

  10. sql 多表多行模糊查询_从零开始学习SQL(五)多表查询

    经过之前的学习,现在我们已经对查询有了一定的了解,但是我们目前的所有查询都只能找到在一张表中的数据,但如果我们需要寻找分布在多张表格中的数据时,这种之前的查询就做不到了,这时就需要引入一种新的查询方法 ...

最新文章

  1. C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)
  2. 关于MySQL连接Navicat Premium 12失败的解决方法
  3. Maven---学习心得---maven的Dependency Mechanism(依赖关系机制)
  4. 启动mysql 1067_启动mysql遇到1067问题
  5. jQuery Ajax 方法调用 Asp.Net WebService 的详细例子
  6. “进度条”博客——第十三周
  7. php pdf怎么转换成jpg图片,如何在线将pdf转换成jpg图片格式?
  8. 抽象代数 04.03 Sylow 子群
  9. 机器学习中的数学——Momentum(Gradient Descent with Momentum, GDM)
  10. python和pyqt5入门之简易汇率转换器
  11. 如何使用python读取modbus/TCP协议数据
  12. MEC与C-V2X融合应用场景白皮书
  13. 2022年低压电工复训题库及在线模拟考试
  14. 赣州php微信群,PHP微信群加群强制分享转发裂变源码
  15. 玩转96boards之(一)---高通410c板硬件
  16. 程序员免费自学编程的8大网站!
  17. 你所不了解的分布性系统之高可用篇
  18. Nvidia Jetson Nano刷机保姆级教程
  19. 前端开发必备之MDN(API查阅文档)
  20. 活跃用户增长与饿了么口碑相差近3倍,美团的下一步去哪儿?

热门文章

  1. java 生成kml文件_java使用dom4j解析大量坐标点的kml文件
  2. php支持微信h5支付,PHP接入微信H5支付的方法示例
  3. 用R语言下载任意地区DEM数据
  4. js 将16进制颜色转为RGBA
  5. BMFont制作字体图集
  6. oracle mysql认证考试流程_报考oraclemysql认证考试流程有些什么步骤
  7. Unity基础知识之协程
  8. 基于C#和SQL SERVER的汉字词典的设计与实现
  9. 杂七杂八(7): win7无法安装python3
  10. cad插入块_软件CAD | 块amp;点工具