2.1 第一个C语言程序
我们有两种方式从计算机获得信息:一是看屏幕上的文字、图片、视频等,二是听从喇叭发出来的声音。让喇叭发出声音目前还比较麻烦,我们先来看看如何在屏幕上显示一些文字吧。
在屏幕上显示文字非常简单,只需要一个语句,例如,下面的代码会让屏幕显示出小马学编程
:
puts("小马学编程");
这里有一个生疏的词汇puts,用来让计算机在屏幕上显示文字。
更加专业的称呼:
- “在屏幕上显示文字”叫做输出(Output);
- 每个文字都是一个字符(Character);
- 多个字符组合起来,就是一个字符序列,叫做字符串(String)。
puts 是 output string 的缩写,意思是”输出字符串“。
在C语言中,字符串需要用双引号” “包围起来,小马学编程
什么也不是,计算机不认识它,"小马学编程"
才是字符串。所以双引号很重要,不要忘记它。
puts 在输出字符串的时候,需要将字符串放在( )内。
在汉语和英语中,分别使用。
和.表示一句话的结束,而在C语言中,使用;
表示一个语句的结束。puts("小马学编程")
表达了完整的意思,是一个完整的语句,需要在最后加上;
,表示当前语句结束了。
总结起来,上面的语句可以分为三个部分:
puts( )
命令计算机输出字符串;"小马学编程"
是要输出的内容;;
表示语句结束。C语言程序的整体框架
puts 可以在显示器上输出内容,但是仅有 puts 是不够的,程序不能运行,还需要添加其他代码,构成一个完整的程序框架。完整的程序如下: ```cinclude
int main() {
puts(“小马学编程”);
return 0;
}
第 1~3 行、第 5~6 行是固定的,所有C语言源代码都必须有这几行。你暂时不需要理解它们是什么意思,反正有这个就是了,以后会慢慢讲解。
但是请记住,今后我们写的所有类似` puts `这样的语句,都必须放在`{ }`之间才有效。
这就是我们的第一个C语言程序,它非常简单,带领我们进入了C语言的大门。
---
<a name="e5qZY"></a>
# 2.2 编程时请选择正确的输入法,严格区分中英文
计算机起源于美国,C语言、C++、Java、JavaScript 等很多流行的编程语言都是美国人发明的,所以在编写代码的时候必须使用**英文半角输入法**,尤其是标点符号,初学者一定要引起注意。
例如,上节我们使用 puts 语句在显示器上输出内容:<br />`puts("C语言中文网");`<br />这里的括号、双引号、分号都必须是英文符号,而且是半角的。下图演示了如何将搜狗输入法切换到英文半角状态:<br /><br />图1:搜狗输入法<br />一些相似的中英文标点符号:
- 中文分号`;`和英文分号`;`;
- 中文逗号`,`和英文逗号`,`;
- 中文冒号`:`和英文冒号`:`;
- 中文括号`()`和英文括号`()`;
- 中文问号`?`和英文问号`?`;
- 中文单引号`‘ ’`和英文单引号`' '`;
- 中文双引号`“ ”`和英文双引号`" "`。
<br />初学者请务必注意标点符号的问题,它们在视觉上的差别很小,一旦将英文符号写成中文符号就会导致错误,而且往往不容易发现。
<a name="RkVXx"></a>
## 全角和半角输入法的区别
全角和半角的区别主要在于除汉字以外的其它字符,比如标点符号、英文字母、阿拉伯数字等,全角字符和半角字符所占用的位置的大小不同。
在计算机屏幕上,一个汉字要占两个英文字符的位置,人们把一个英文字符所占的位置称为“半角”,相对地把一个汉字所占的位置称为“全角”。
标点符号、英文字母、阿拉伯数字等这些字符不同于汉字,在半角状态它们被作为英文字符处理,而在全角状态作为中文字符处理,请看下面的例子。
半角输入:<br />`小马学编程!Hello C,I like!`<br />全角输入:<br />`小马学编程!Hello C,I like!`
另外最重要的一点是:“相同”字符在全角和半角状态下对应的编码值(例如 Unicode 编码、GBK 编码等)不一样,所以对于计算机来讲它们是不同的字符。
<br />图:搜狗输入法半角和全角
我们知道,在编程时要使用英文半角输入法。为了加强练习,出个选择题,请大家判断下面哪一种描述是正确的:<br />A) 编程的时候不用在意中英文符号的区别。<br />B) 在源代码的任何地方都不能出现中文汉字、字符等。<br />C) 感叹号没有中文和英文的区别。<br />D) 编程时,使用的英文引号,也有左引号和右引号的区别。<br />_E) 中文和英文模式下的制表符(键盘tab键)输入效果一致。_
---
<a name="W8bzH"></a>
# 2.3 什么是源文件?
在开发软件的过程中,我们需要将编写好的代码(Code)保存到一个文件中,这样代码才不会丢失,才能够被编译器找到,才能最终变成可执行文件。这种用来保存代码的文件就叫做源文件(Source File)。<br />我们将在《[编译和链接](http://c.biancheng.net/view/1736.html)》一节中讲解编译器的概念。<br />每种编程语言的源文件都有特定的后缀,以方便被编译器识别,被程序员理解。源文件后缀大都根据编程语言本身的名字来命名,例如:
- C语言源文件的后缀是`.c`;
- [C++](http://c.biancheng.net/cplus/)语言(C Plus Plus)源文件的后缀是`.cpp`;
- [Java](http://c.biancheng.net/java/) 源文件的后缀是`.java`;
- [Python](http://c.biancheng.net/python/) 源文件的后缀是`.py`;
- [JavaScript](http://c.biancheng.net/js/) 源文件后置是`.js`。
<br />源文件其实就是纯文本文件,它的内部并没有特殊格式,能证明这一结论的典型例子是:在 Windows 下用记事本程序新建一个文本文档,并命名为`demo.txt`,输入一段C语言代码并保存,然后将该文件强制重命名为`demo.c`(后缀从`.txt`变成了`.c`),发现编译器依然能够正确识别其中的C语言代码,并顺利生成可执行文件。
源文件的后缀仅仅是为了表明该文件中保存的是某种语言的代码(例如`.c`文件中保存的是C语言代码),这样程序员更加容易区分,编译器也更加容易识别,它并不会导致该文件的内部格式发生改变。
[C++](http://c.biancheng.net/cplus/) 是站在C语言的肩膀上发展起来的,是在C语言的基础上进行的扩展,C++ 包含了C语言的全部内容(请猛击《[C语言和C++到底有什么关系](https://www.yuque.com/myw/cc/gc3fld#EsLiq)》一文了解更多),将C语言代码放在`.cpp`文件中不会有错,很多初学者都是这么做的,很多大学老师也是这么教的。但是,我还是强烈建议将C语言代码放在`.c`文件中,这样能够更加严格地遵循C语言的语法,也能够更加清晰地了解C语言和C++的区别。
---
<a name="UzDXR"></a>
# 2.4 C语言编译和链接详解(通俗易懂,深入本质)
我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有`.exe`和`.com`(其中.exe比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判断是否是可执行程序。
可执行程序的内部是一系列计算机指令和数据的集合,它们都是二进制形式的,CPU 可以直接识别,毫无障碍;但是对于程序员,它们非常晦涩,难以记忆和使用。
例如,在屏幕上输出“VIP会员”,C语言的写法为:<br />`puts("VIP会员");`<br />二进制的写法为:<br />
你感受一下,直接使用二进制是不是想撞墙,是不是受到一吨重的伤害?
> 在计算机发展的初期,程序员就是使用这样的二进制指令来编写程序的,那个拓荒的年代还没有编程语言。
直接使用二进制指令编程对程序员来说简直是噩梦,尤其是当程序比较大的时候,不但编写麻烦,需要频繁查询指令手册,而且除错会异常苦恼,要直接面对一堆二进制数据,让人眼花缭乱。另外,用二进制指令编程步骤繁琐,要考虑各种边界情况和底层问题,开发效率十分低下。
这就倒逼程序员开发出了编程语言,提高自己的生产力,例如汇编、C语言、[C++](http://c.biancheng.net/cplus/)、[Java](http://c.biancheng.net/java/)、[Python](http://c.biancheng.net/python/)、Go语言等,都是在逐步提高开发效率。至此,编程终于不再是只有极客能做的事情了,不了解计算机的读者经过一定的训练也可以编写出有模有样的程序。
<a name="FJN6V"></a>
## 编译(Compile)
C语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于CPU,C语言代码就是天书,根本不认识,CPU只认识几百个二进制形式的指令。这就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成` .exe `程序的格式;这个工具是一个特殊的软件,叫做**编译器(Compiler)**。
编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为**编译(Compile)**。
编译也可以理解为**“翻译”**,类似于将中文翻译成英文、将英文翻译成象形文字,它是一个复杂的过程,大致包括词法分析、语法分析、语义分析、性能优化、生成可执行文件五个步骤,期间涉及到复杂的算法和硬件架构。对于学计算机或者软件的大学生,“编译原理”是一门专业课程,有兴趣的读者请自行阅读《[编译原理](https://book.douban.com/subject/3296317/)》一书,这里我们不再展开讲解。
> 注意:不了解编译原理并不影响我们学习C语言,我也不建议初学者去钻研编译原理,贪多嚼不烂,不要把自己绕进去。
C语言的编译器有很多种,不同的平台下有不同的编译器,例如:
- Windows 下常用的是微软开发的 Visual C++,它被集成在 Visual Studio 中,一般不单独使用;
- Linux 下常用的是 GUN 组织开发的 [GCC](http://c.biancheng.net/gcc/),很多 Linux 发行版都自带 GCC;
- Mac 下常用的是 LLVM/Clang,它被集成在 Xcode 中(Xcode 以前集成的是 GCC,后来由于 GCC 的不配合才改为 LLVM/Clang,LLVM/Clang 的性能比 GCC 更加强大)。
<br />你的代码语法正确与否,编译器说了才算,我们学习C语言,从某种意义上说就是学习如何使用编译器。
编译器可以 100% 保证你的代码从语法上讲是正确的,因为哪怕有一点小小的错误,编译也不能通过,编译器会告诉你哪里错了,便于你的更改。
<a name="IiVpd"></a>
## 链接(Link)
C语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成了一种叫做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是`.obj`;对于 GCC,目标文件的后缀是`.o`。
目标文件经过**链接(Link)**以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,直接作为可执行文件不行吗?
不行的!因为编译只是将我们自己写的代码变成了二进制形式,它还需要和系统组件(比如标准库、动态链接库等)结合起来,这些组件都是程序运行所必须的。
**链接(Link)**其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做**链接器(Linker)**。
随着我们学习的深入,我们编写的代码越来越多,最终需要将它们分散到多个源文件中,编译器每次只能编译一个源文件,生成一个目标文件,这个时候,链接器除了将目标文件和系统组件组合起来,还需要将编译器生成的多个目标文件组合起来。
再次强调,编译是针对一个源文件的,有多少个源文件就需要编译多少次,就会生成多少个目标文件。
<a name="NXFla"></a>
## 总结
不管我们编写的代码有多么简单,都必须经过`「编译 --> 链接」`的过程才能生成可执行文件:
- 编译就是将我们编写的源代码“翻译”成计算机可以识别的二进制格式,它们以目标文件的形式存在;
- 链接就是一个“打包”的过程,它将所有的目标文件以及系统组件组合成一个可执行文件。
<br />如果不是特别强调,一般情况下我们所说的“编译器”实际上也包括了链接器,比如,你使用了哪种编译器?去哪里下载C语言编译器?我的编译器为什么报错了呢?
---
<a name="ejwWa"></a>
# 2.5 C语言编译器(C语言编程软件)完全攻略(包含所有平台)
在上节《[C语言编译和链接](http://c.biancheng.net/view/144.html)》中我们已经讲解了C语言编译器的概念,由于C语言的历史比较久,而且早期没有规范,整个计算机产业也都处于拓荒的年代,所以就涌现了很多款C语言编译器,它们各有特点,适用于不同的平台,本节就来给大家科普一下。
我们分两部分介绍C语言的编译器,分别是桌面操作系统和嵌入式操作系统。
<a name="X9nKg"></a>
## 桌面操作系统
对于当前主流桌面操作系统而言,可使用 Visual [C++](http://c.biancheng.net/cplus/)、[GCC](http://c.biancheng.net/gcc/) 以及 LLVM Clang 这三大编译器。
Visual C++(简称 MSVC)是由微软开发的,只能用于 Windows 操作系统;GCC 和 LLVM Clang 除了可用于 Windows 操作系统之外,主要用于 Unix/Linux 操作系统。
像现在很多版本的 Linux 都默认使用 GCC 作为C语言编译器,而像 FreeBSD、macOS 等系统默认使用 LLVM Clang 编译器。由于当前 LLVM 项目主要在 Apple 的主推下发展的,所以在 macOS中,Clang 编译器又被称为 Apple LLVM 编译器。
MSVC 编译器主要用于 Windows 操作系统平台下的应用程序开发,它不开源。用户可以使用 Visual Studio Community 版本来免费使用它,但是如果要把通过 Visual Studio Community 工具生成出来的应用进行商用,那么就得好好阅读一下微软的许可证和说明书了。
而使用 GCC 与 Clang 编译器构建出来的应用一般没有任何限制,程序员可以将应用程序随意发布和进行商用。
MSVC 编译器对 C99 标准的支持就十分有限,加之它压根不支持任何 C11 标准,所以本教程中设计 C11 的代码例子不会针对 MSVC 进行描述。所幸的是,Visual Studio Community 2017 加入了对 Clang 编译器的支持,官方称之为——Clang with Microsoft CodeGen,当前版本基于的是 Clang 3.8。
也就是说,应用于 Visual Studio 集成开发环境中的 Clang 编译器前端可支持 Clang 编译器的所有语法特性,而后端生成的代码则与 MSVC 效果一样,包括像 long 整数类型在 64 位编译模式下长度仍然为 4 个字节,所以各位使用的时候也需要注意。
为了方便描述,本教程后面涉及 Visual Studio 集成开发环境下的 Clang 编译器简称为 VS-Clang 编译器。
<a name="G5rZJ"></a>
## 嵌入式系统
而在嵌入式系统方面,可用的C语言编译器就非常丰富了,比如:
- 用于 Keil 公司 51 系列单片机的 Keil C51 编译器;
- 当前大红大紫的 Arduino 板搭载的开发套件,可用针对 AVR 微控制器的 AVR GCC 编译器;
- ARM 自己出的 ADS(ARM Development Suite)、RVDS(RealView Development Suite)和当前最新的 DS-5 Studio;
- DSP 设计商 TI(Texas Instruments)的 CCS(Code Composer Studio);
- DSP 设计商 ADI(Analog Devices,Inc.)的 Visual DSP++ 编译器,等等。
<br />通常,用于嵌入式系统开发的编译工具链都没有免费版本,而且一般需要通过国内代理进行购买。所以,这对于个人开发者或者嵌入式系统爱好者而言是一道不低的门槛。
不过 Arduino 的开发套件是可免费下载使用的,并且用它做开发板连接调试也十分简单。Arduino 所采用的C编译器是基于 GCC 的。
还有像树莓派(Raspberry Pi)这种迷你电脑可以直接使用 GCC 和 Clang 编译器。此外,还有像 nVidia 公司推出的 Jetson TK 系列开发板也可直接使用 GCC 和 Clang 编译器。树莓派与 Jetson TK 都默认安装了 Linux 操作系统。
在嵌入式领域,一般比较低端的单片机,比如 8 位的 MCU 所对应的C编译器可能只支持 C90 标准,有些甚至连 C90 标准的很多特性都不支持。因为它们一方面内存小,ROM 的容量也小;另一方面,本身处理器机能就十分有限,有些甚至无法支持函数[指针](http://c.biancheng.net/c/80/),因为处理器本身不包含通过寄存器做间接过程调用的指令。
而像 32 位处理器或 DSP,一般都至少能支持 C99 标准,它们本身的性能也十分强大。而像 ARM 出的 RVDS 编译器甚至可用 GNU 语法扩展。
下图展示了上述C语言编译器的分类。<br />
<a name="UUgbr"></a>
# 2.6 什么是IDE(集成开发环境)?
实际开发中,除了编译器是必须的工具,我们往往还需要很多其他辅助软件,例如:
- 编辑器:用来编写代码,并且给代码着色,以方便阅读;
- 代码提示器:输入部分代码,即可提示全部代码,加速代码的编写过程;
- 调试器:观察程序的每一个运行步骤,发现程序的逻辑错误;
- 项目管理工具:对程序涉及到的所有资源进行管理,包括源文件、图片、视频、第三方库等;
- 漂亮的界面:各种按钮、面板、菜单、窗口等控件整齐排布,操作更方便。
<br />这些工具通常被打包在一起,统一发布和安装,例如 Clion 、 Visual Studio、Dev C++、Xcode、Visual C++ 6.0、C-Free、Code::Blocks 等,它们统称为集成开发环境(IDE,Integrated Development Environment)。
集成开发环境就是一系列开发工具的组合套装。这就好比台式机,一个台式机的核心部件是主机,有了主机就能独立工作了,但是我们在购买台式机时,往往还要附带上显示器、键盘、鼠标、U盘、摄像头等外围设备,因为只有主机太不方便了,必须有外设才能玩的爽。
集成开发环境也是这个道理,只有编译器不方便,所以还要增加其他的辅助工具。在实际开发中,我一般也是使用集成开发环境,而不是单独地使用编译器。
<a name="iVoJU"></a>
#### 通俗的称呼
有时候为了称呼方便,或者初学者没有严格区分概念,也会将C语言集成开发环境称作“C语言编译器”或者“C语言编程软件”。这里大家不要认为是一种错误,就把它当做“乡间俗语”吧。
<a name="H5Ewc"></a>
# 2.7 什么是工程/项目?
一个真正的程序(也可以说软件)往往包含多项功能,每一项功能都需要几十行甚至几千行、几万行的代码来实现,如果我们将这些代码都放到一个源文件中,那将会让人崩溃,不但源文件打开速度极慢,代码的编写和维护也将变得非常困难。
在实际开发中,程序员都是将这些代码分门别类地放到多个源文件中。除了这些成千上万行的代码,一个程序往往还要包含图片、视频、音频、控件、库(也可以说框架)等其它资源,它们也都是一个一个地文件。
为了有效地管理这些种类繁杂、数目众多的文件,我们有理由把它们都放到一个目录(文件夹)下,并且这个目录下只存放与当前程序有关的资源。实际上 IDE 也是这么做的,它会为每一个程序都创建一个专门的目录,将用到的所有文件都集中到这个目录下,并对它们进行便捷的管理,比如重命名、删除文件、编辑文件等。
这个为当前程序配备的专用文件夹,在 IDE 中也有一个专门的称呼,叫做“Project”,翻译过来就是“工程”或者“项目”。在 Visual [C++](http://c.biancheng.net/cplus/) 6.0 下,这叫做一个“工程”,而在 Visual Studio 下,这又叫做一个“项目”,它们只是单词“Project”的不同翻译而已,实际上是一个概念。
<a name="KVdx7"></a>
## 工程类型/项目类型
“程序”是一个比较宽泛的称呼,它可以细分为很多种类,例如:
- 有的程序不带界面,完全是“黑屏”的,只能输入一些字符或者命令,称为控制台程序(Console Application),例如 Windows 下的 cmd.exe,Linux 或 Mac OS 下的终端(Terminal)。
- 有的程序带界面,看起来很漂亮,能够使用鼠标点击,称为GUI程序(Graphical User Interface Program),例如 QQ、迅雷、Chrome 等。
- 有的程序不单独出现,而是作为其它程序的一个组成部分,普通用户很难接触到它们,例如静态库、动态库等。
<br />不同的程序对应不同的工程类型(项目类型),使用 IDE 时必须选择正确的工程类型才能创建出我们想要的程序。换句话说,IDE 包含了多种工程类型,不同的工程类型会创建出不同的程序。
不同的工程类型本质上是对 IDE 中各个参数的不同设置;我们也可以创建一个空白的工程类型,然后自己去设置各种参数(不过一般不这样做)。
控制台程序对应的工程类型为“Win32控制台程序(Win32 Console Application)”,GUI 程序对应的工程类型为“Win32程序(Win32 Application)”。
控制台程序是 DOS 时代的产物了,它没有复杂的功能,没有漂亮的界面,只能看到一些文字,虽然枯燥无趣,也不实用,但是它非常简单,不受界面的干扰,所以适合入门,我强烈建议初学者从控制台程序学起。等大家对编程掌握的比较熟练了,能编写上百行的代码了,再慢慢过渡到 GUI 程序。
---
<a name="Fpt50"></a>
# 2.8 哪款C语言编译器(IDE)适合初学者?
> 这里我们把“编译器”和“IDE(集成开发环境)”当做一个概念,不再加以区分。
C语言的集成开发环境有很多种,尤其是 Windows 下,多如牛毛,初学者往往不知道该如何选择,本节我们就针对 Windows、Linux 和 Mac OS 三大平台进行讲解。
<a name="qU0Yf"></a>
## Windows 下如何选择 IDE?
Windows 下的 IDE 多如牛毛,常见的有以下几种。
<a name="yxLB7"></a>
### 1) Visual Studio
Windows 下首先推荐大家使用微软开发的 Visual Studio(简称 VS),它是 Windows 下的标准 IDE,实际开发中大家也都在使用。
为了适应最新的 Windows 操作系统,微软每隔一段时间(一般是一两年)就会对 VS 进行升级。VS 的不同版本以发布年份命名,例如 VS2010 是微软于 2010 年发布的,VS2017 是微软于 2017 年发布的。
不过 VS 有点庞大,安装包有 2~3G,下载不方便,而且会安装很多暂时用不到的工具,安装时间在半个小时左右。
**对于初学者,我推荐使用 VS2015。最好不用使用 VS2017,有点坑初学者。**
<a name="rOCDf"></a>
### 2) Dev C++ 马老师推荐这个
[官方下载----可能受限于网速或者不稳定](https://sourceforge.net/projects/orwelldevcpp/)<br />[马老师百度云盘下载](https://pan.baidu.com/s/1-ZfmlK3QwEUSYj2ZTXNdYQ?pwd=mayw)<br />[马老师123云盘下载](https://www.123pan.com/s/A7oDVv-olY4H)<br />如果你讨厌 VS 的复杂性,那么可以使用 Dev C++。Dev C++ 是一款免费开源的 C/C++ IDE,内嵌 [GCC](http://c.biancheng.net/gcc/) 编译器(Linux GCC 编译器的 Windows 移植版),是 NOI、NOIP 等比赛的指定工具。Dev C++ 的优点是体积小(只有几十兆)、安装卸载方便、学习成本低,缺点是调试功能弱。
> NOI 是National Olympiad in Informatics的缩写,译为“全国青少年信息学奥林匹克竞赛”;NOIP 是National Olympiad in informatics in Pro[vi](http://c.biancheng.net/vi/)nces的缩写,译为“全国青少年信息学奥林匹克联赛”。NOI、NOIP 都是奥林匹克竞赛的一种,参加者多为高中生,获奖者将被保送到名牌大学或者得到高考加分资格。
<a name="c3WVx"></a>
### 3) Visual C++ 6.0
Visual C++ 6.0(简称VC 6.0)是微软开发的一款经典的 IDE,很多高校都以 VC 6.0 为教学工具来讲解C和C++。但VC 6.0是1998年的产品,很古老了,在 Win7、Win8、Win10 下会有各种各样的兼容性问题,甚至根本不能运行,所以不推荐使用。
VC 6.0 早就该扔进垃圾桶了,可是依然有很多大学把它作为教学工具,并且选用的教材也以 VC 6.0 为基础来讲解C语言和 C++,可见教学体制的极端落后,课程体系的更新远远跟不上技术的进步。
<a name="vSeHG"></a>
### 4) Code::Blocks
Code::Blocks 是一款开源、跨平台、免费的 C/C++ IDE,它和 Dev C++ 非常类似,小巧灵活,易于安装和卸载,不过它的界面要比 Dev C++ 复杂一些,不如 Dev C++ 来得清爽。
<a name="tINRd"></a>
### 5) Turbo C
Turbo C 是一款古老的、DOS 年代的C语言开发工具,程序员只能使用键盘来操作 Turbo C,不能使用鼠标,所以非常不方便。但是 Turbo C 集成了一套图形库,可以在控制台程序中画图,看起来非常炫酷,所以至今仍然有人在使用。
<a name="GfpPw"></a>
### 6) C-Free
C-Free 是一款国产的 Windows 下的C/C++ IDE,最新版本是 5.0,整个软件才 14M,非常轻巧,安装也简单,界面也比 Dev C++ 漂亮。C-Free 的缺点也是调试功能弱。可惜的是,C-Free 已经多年不更新了,组件都老了,只能在 XP、Win7 下运行,在 Win8、Win10 下可能会存在兼容性问题。
<a name="VhgCp"></a>
### 7) Clion
jetbrains公司出品的诸多编辑器都超级只能且好用.像IDEA ,PyCharm,等都是非常著名的软件.对于的C语言也有Clion编辑器.<br />如果习惯了jetbrains公司的产品,可以考虑使用.<br />缺点是需要关联编译器.<br />[clion使用方法](https://www.yuque.com/myw/ruanjian/cclion)
---
下面我们给出了各种 IDE(含不同版本)的下载地址、安装方法以及使用教程,并以红色字体附带了建议。
- **VS2015 [荐]**
- [VS2015下载地址和安装教程(图解)](http://c.biancheng.net/view/453.html)
- [使用VS2015编写C语言程序](http://c.biancheng.net/view/454.html)
- **VS2017**
- [VS2017下载地址和安装教程(图解)](http://c.biancheng.net/view/456.html)
- [使用VS2017编写C语言程序](http://c.biancheng.net/view/457.html)
- **VS2010 [荐]**
- [VS2010下载地址和安装教程(图解)](http://c.biancheng.net/view/458.html)
- [使用VS2010编写C语言程序](http://c.biancheng.net/view/459.html)
- **Dev C++ [荐荐荐]**
- [Dev C++下载地址和安装教程(图解)](http://c.biancheng.net/view/461.html)
- [使用Dev C++编写C语言程序](http://c.biancheng.net/view/462.html)
- **VC6.0 [不建议]**
- [VC6.0(VC++6.0)下载地址和安装教程(图解)](http://c.biancheng.net/view/463.html)
- [使用VC6.0(VC++6.0)编写C语言程序](http://c.biancheng.net/view/464.html)
- **Code::Blocks**
- [Code::Blocks下载地址和安装教程(图解)](http://c.biancheng.net/view/465.html)
- [Code::Blocks汉化教程(附带汉化包)](http://c.biancheng.net/view/466.html)
- [使用Code::Blocks编写C语言程序](http://c.biancheng.net/view/467.html)
- **Turbo C [不建议]**
- [Turbo C 2.0下载地址和安装教程(图解)](http://c.biancheng.net/view/468.html)
- [使用Turbo C 2.0编写C语言程序](http://c.biancheng.net/view/469.html)
- **C-Free [不建议]**
- [C-Free 5.0下载地址和激活教程(图解)](http://c.biancheng.net/view/470.html)
- [使用C-Free编写C语言程序](http://c.biancheng.net/view/472.html)
---
<a name="i7ivL"></a>
## Linux 下如何选择 IDE?
Linux 下可以不使用 IDE,只使用 GCC 编译器和一个文本编辑器(例如 Gedit)即可,这样对初学者理解C语言程序的生成过程非常有帮助,请参考:[Linux GCC简明教程(使用GCC编写C语言程序)](http://c.biancheng.net/view/475.html)
当然,如果你希望使用 IDE,那么可以选择 CodeLite、Code::Blocks、Anjuta、Eclipse、NetBeans 等。
---
<a name="l1ie5"></a>
## Mac OS 下如何选择 IDE?
Mac OS 下推荐使用 Apple 官方开发的 Xcode,在 APP Store 即可下载,具体请参见:[Xcode简明教程(使用Xcode编写C语言程序)](http://c.biancheng.net/view/476.html)
另外,Visual Studio 也推出了 Mac 版本,已经习惯了 Visual Studio 的用户可以高兴一把了。
---
<a name="o1KQX"></a>
# 2.9 C89(C90)、C99、C11——C语言的三套标准
C语言最初由 Dennis Ritchie 于 1969 年到 1973 年在 AT&T 贝尔实验室里开发出来,主要用于重新实现 Unix 操作系统。此时,C语言又被称为 K&R C。其中,K 表示 Kernighan 的首字母,而 R 则是 Ritchie 的首字母。
K&R C语言与后来标准化的C语言有很大差异,比如:
- 如果函数返回类型为 int,则 int 可省:<br />`int my_function(){ }`也可以写成`my_function(){ }`编译器不会有任何警告,更不会报错。
- 还有现在看来比较奇葩的函数定义,像我们现在定义这么一个函数:`void my_function(int a, char*p) {}`如果是用 K&R C 语法定义的话要写成:`void my_function(a,p)int a; char*p; {}`K&R 的C语法中,定义一个函数时,其形参列表先列出形参的标识符,然后在函数声明的后面紧跟着对形参标识符的完整声明,最后是函数体。这在现行标准中已经被逐步废弃使用了。
<br />另外,当时的第一本C语言专业书《The C Programming Language》也并非一个正式的编程语言规范,但被用了许多年。
<a name="ffn7e"></a>
## C90 标准
由于C语言被各大公司所使用(包括当时处于鼎盛时期的 IBM PC),因此到了 1989 年,C语言由美国国家标准协会(ANSI)进行了标准化,此时C语言又被称为 ANSI C。
而仅过一年,ANSI C 就被国际标准化组织 ISO 给采纳了。此时,C语言在 ISO 中有了一个官方名称——ISO/IEC 9899: 1990。其中:
- 9899 是C语言在 ISO 标准中的代号,像 C++ 在 ISO 标准中的代号是 14882;
- 而冒号后面的 1990 表示当前修订好的版本是在 1990 年发布的。
<br />对 于ISO/IEC 9899: 1990 的俗称或简称,有些地方称为 C89,有些地方称为 C90,或者 C89/90。不管怎么称呼,它们都指代这个最初的C语言国际标准。
这个版本的C语言标准作为 K&R C 的一个超集(即 K&R C 是此标准C的一个子集),把后来引入的许多非官方特性也一起整合了进去。其中包括了从 C++ 借鉴的函数原型(Function Prototypes),指向 void 的指针,对国际字符集以及本地语言环境的支持。在此标准中,尽管已经将函数定义的方式改为现在我们常用的那种方式,不过K&R的语法形式仍然兼容。
<a name="Kybbg"></a>
## C99标准
在随后的几年里,C语言的标准化委员会又不断地对C语言进行改进,到了 1999 年,正式发布了 ISO/IEC 9899: 1999,简称为 C99 标准。
C99 标准引入了许多特性,包括内联函数(inline functions)、可变长度的数组、灵活的数组成员(用于结构体)、复合字面量、指定成员的初始化器、对IEEE754浮点数的改进、支持不定参数个数的宏定义,在数据类型上还增加了 long long int 以及复数类型。
毫不夸张地说,即便到目前为止,很少有C语言编译器是完整支持 C99 的。像主流的 GCC 以及 Clang 编译器都能支持高达90%以上,而微软的 Visual Studio 2015 中的C编译器只能支持到 70% 左右。
<a name="A3uqA"></a>
## C11标准
2007 年,C语言标准委员会又重新开始修订C语言,到了 2011 年正式发布了 ISO/IEC 9899: 2011,简称为 C11 标准。
C11标准新引入的特征尽管没 C99 相对 C90 引入的那么多,但是这些也都十分有用,比如:字节对齐说明符、泛型机制(generic selection)、对多线程的支持、静态断言、原子操作以及对 Unicode 的支持。
关于C语言历史与演化进程的详细介绍可参考维基百科:[https://en.wikipedia.org/wiki/C_%28programming_language](https://en.wikipedia.org/wiki/C_%28programming_language)。
---
<a name="KTVbP"></a>
# 2.10 C语言为什么有那么多编译器?
<br />通过上节《C语言的三套标准:C89、C99和C11》的介绍可以发现,C语言并没有一个官方机构,也不属于哪个公司,它只有一个制定标准的委员会,任何其他组织或者个人都可以开发C语言的编译器,而这个编译器要遵守哪个C语言标准,是 100% 遵守还是部分遵守,并没有强制性的措施,也没有任何约束。
换句话说,各个厂商可以为了自己的利益、根据自己的喜好来开发编译器。
这就导致了一个棘手的问题,有的编译器遵守较新的C语言标准,有的编译器只能遵守较老的C语言标准,有的编译器还进行了很多扩展。比如:
- GCC、LLVM/Clang 更新非常及时,能够支持最新的 C11 标准(前提是你得使用最新版的编译器)。
- 微软编译器更新比较缓慢,迟迟不能支持新标准,例如 VC 6.0、VS2010 都在使用 C89 标准,VS2015 部分支持 C99 标准(其他版本的VS没有测试)。微软官方给出的答复是,最新的标准已经在 C++ 中支持了,C语言就没必要再重复了。
初学者经常会遇到这种情况,有些代码在微软编译器下能够正常运行,拿到 [GCC](https://so.csdn.net/so/search?q=GCC&spm=1001.2101.3001.7020) 下就不行了,一堆报错信息;或者反过来,在 GCC 上能运行的代码在微软编译器下不能运行。这是因为不同的编译器支持不同的标准,并且每个编译器都进行了自己的扩展,假如你使用了微软编译器私有的扩展函数,那么拿到 GCC 下肯定是不支持的。
---
<a name="DfpBJ"></a>
# 2.11 C语言为什么有那么多编译器?
我们知道,大部分软件都需要先安装才能使用,例如 QQ、360、迅雷等,要先从网上下载一个安装包,然后安装到计算机的C盘或者D盘等。大部分程序还会在开始菜单或者桌面上生成一个快捷方式,用户只要点击快捷方式,就可以启动软件。
那么,一个程序为什么要安装呢?下载后直接使用不可以吗?下面我们就来分析一下。
不同的操作系统,安装软件的方法虽然不一样,但基本原理是相同的,主要的思想就是将程序的**二进制**可执行文件拷贝到某个目录,设置一些路径。如果程序运行时需要一些库,将这些库拷贝到系统目录即可。
程序的安装基本上要经过下面四个步骤:
**1) 将程序的可执行文件从安装包所在的位置,拷贝到要安装的目录。**<br />安装程序的时候,程序会给用户指定一个默认的安装目录,如果用户需要,也可以自定义安装,改变安装目录。一般所谓的“绿色软件”到此就安装结束了,可以使用了。
**2) 如果有必要,可以向系统目录拷贝一些动态链接库(DLL)。(可选操作)**<br />有的程序,比如大型游戏,可能需要很多动态链接库(DLL)的支持,这时候程序可能会将这些 DLL 拷贝到系统库的默认目录,Win7 下一般拷贝到C:\\Windows\System32\(读者不妨打开该目录,会看到很多 DLL 文件)。
有些程序用到的 DLL 文件不是系统必需的,只能由程序自己使用,这样放在系统目录里就不太合适,安装的软件多了,就会造成系统臃肿,所以这些 DLL 会被拷贝到程序的安装目录。
**3) 向系统注册表中写入相应的设置项,注册程序或者库的安装信息。(可选操作)**<br />安装前,用户可能会对软件做一些设置,安装时,这些设置就会被写入注册表。另外,当安装程序将 DLL 文件拷贝到系统目录时,一些 DLL 还需要向系统注册,告诉系统我在这里,不然使用的时候可能会找不到。
**4) 在开始菜单或者桌面上位程序创建快捷方式。(可选操作)**<br />创建快捷方式主要是为了用户使用方便,有了快捷方式,就不用再到安装目录去启动程序了。
由此可见,程序在安装前后并没有什么区别,只不过是进行了一些设置,有的设置是程序运行所必须的,有的是为了让用户更加方便。
---
<a name="euyRb"></a>
# 2.12 C语言程序的错误和警告
一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题。编译器只能检查编译和链接阶段出现的问题,而可执行程序已经脱离了编译器,运行阶段出现问题编译器是无能为力的。
如果我们编写的代码正确,运行时会提示没有错误(Error)和警告(Warning),如下图所示:<br /><br />图1:Dev C++ 的提示
<br />图2:VC 6.0 的提示
<br />图3:C-Free 5.0 的提示
> 对于 VS、GCC、Xcode 等,如果代码没有错误,它们只会显示“生成成功”,不会显示“0个错误,0个警告”,只有代码真的出错了,它们才会显示具体的错误信息。
错误(Error)表示程序不正确,不能正常编译、链接或运行,必须要纠正。
警告(Warning)表示可能会发生错误(实际上未发生)或者代码不规范,但是程序能够正常运行,有的警告可以忽略,有的要引起注意。
错误和警告可能发生在编译、链接、运行的任何时候。
例如,`puts("小马学编程")`最后忘记写分号;,就会出现错误,如下图所示:<br /><br />图4:VS2015 的错误提示
<br />图5:Dev C++ 的错误提示
<br />图6:VC 6.0 的错误提示
<br />图7:C-Free 5.0 的错误提示
可以看出,C-Free 的错误提示信息比较少,不方便程序员纠错。VC 和 VS 的错误信息类似,只是中英文的差别。
下图分析了 VC 6.0 的错误信息:<br /><br />图8:错误信息说明
翻译:`源文件 E:\cDemo\hello.c 第5行发生了语法错误,错误代码是 C2143,原因是 'return' 前面丢失了 ';'。`
我敢保证,你写的代码肯定会发生错误,一定要有分析错误的能力,这是一个合格的程序员必备的技能。
---
<a name="D9Afr"></a>
# 2.13 分析第一个C语言程序
前面我们给出了一段最简单的C语言代码,并演示了如何在不同的平台下进行编译,这节我们来分析一下这段代码,让读者有个整体的认识。代码如下:
```c
#include <stdio.h>
int main()
{
puts("小马学编程");
return 0;
}
函数的概念
先来看第 4 行代码,这行代码会在显示器上输出"小马学编程"
。前面我们已经讲过,puts 后面要带( )
,字符串也要放在( )
中。
在C语言中,有的语句使用时不能带括号,有的语句必须带括号。带括号的称为函数(Function)。
C语言提供了很多功能,例如输入输出、获得日期时间、文件操作等,我们只需要一句简单的代码就能够使用。但是这些功能的底层都比较复杂,通常是软件和硬件的结合,还要要考虑很多细节和边界,如果将这些功能都交给程序员去完成,那将极大增加程序员的学习成本,降低编程效率。
好在C语言的开发者们为我们做了一件好事,他们已经编写了大量代码,将常见的基本功能都完成了,我们可以直接拿来使用。但是现在问题来了,那么多代码,如何从中找到自己需要的呢?一股脑将所有代码都拿来显然是非常不明智的。
这些代码,早已被分门别类地放在了不同的文件中,并且每一段代码都有唯一的名字。使用代码时,只要在对应的名字后面加上( )
就可以。这样的一段代码能够独立地完成某个功能,一次编写完成后可以重复使用,被称为函数(Function)。读者可以认为,函数就是一段可以重复使用的代码。
函数的一个明显特征就是使用时必须带括号( )
,必要的话,括号中还可以包含待处理的数据。例如puts("小马学编程")
就使用了一段具有输出功能的代码,这段代码的名字是 puts,"小马学编程"
是要交给这段代码处理的数据。使用函数在编程中有专业的称呼,叫做函数调用(Function Call)。
如果函数需要处理多个数据,那么它们之间使用逗号,
分隔,例如:pow(10, 2);
该函数用来求10的2次方。
需要注意的是,C语言中的函数和数学中的函数不是同一个概念,不要拿两者对比。函数的英文名称是 Function,它还有“功能”的意思。大陆将 Function 翻译为“函数”,而台湾地区翻译为“函式”,读者要注意区分。
自定义函数和main函数
C语言自带的函数称为库函数(Library Function)。库(Library)是编程中的一个基本概念,可以简单地认为它是一些列函数的集合,在磁盘上往往是一个文件夹。C语言自带的库称为标准库(Standard Library),其他公司或个人开发的库称为第三方库(Third-Party Library)。
除了库函数,我们还可以编写自己的函数,拓展程序的功能。自己编写的函数称为自定义函数。自定义函数和库函数在编写和使用方式上完全相同,只是由不同的机构来编写。
示例中第2~6行代码就是我们自己编写的一个函数。main 是函数的名字,( ) 表明这是函数定义,{ } 之间的代码是函数要实现的功能。
函数可以接收待处理的数据,同样可以将处理结果告诉我们;使用return可以告知处理结果。示例中第5行代码表明,main 函数的处理结果是整数 0。return 可以翻译为“返回”,所以函数的处理结果被称为返回值(Return Value)。
第2行代码中,int 是 integer 的简写,意为“整数”。它告诉我们,函数的返回值是整数。
需要注意的是,示例中的自定义函数必须命名为 main。C语言规定,一个程序必须有且只有一个 main 函数。main 被称为主函数,是程序的入口函数,程序运行时从 main 函数开始,直到 main 函数结束(遇到 return 或者执行到函数末尾时,函数才结束)。
也就是说,没有 main 函数程序将不知道从哪里开始执行,运行时会报错。
综上所述:第2~6行代码定义了主函数main
,它的返回值是整数 0
,程序将从这里开始执行。main 函数的返回值在程序运行结束时由系统接收。
有的教材中将 main 函数写作:
void main() {
// Some Code...
}
这在 VC6.0 下能够通过编译,但在 C-Free、GCC 中却会报错,因为这不是标准的 main 函数的写法,大家不要被误导,最好按照示例中的格式来写。
头文件的概念
还有最后一个问题,示例中第1行的#include <stdio.h>
是什么意思呢?
C语言开发者们编写了很多常用函数,并分门别类的放在了不同的文件,这些文件就称为头文件(header file)。每个头文件中都包含了若干个功能类似的函数,调用某个函数时,要引入对应的头文件,否则编译器找不到函数。
实际上,头文件往往只包含函数的说明,也就是告诉我们函数怎么用,而函数本身保存在其他文件中,在链接时才会找到。对于初学者,可以暂时理解为头文件中包含了若干函数。
引入头文件使用#include
命令,并将文件名放在< >
中,#include
和< >
之间可以有空格,也可以没有。
头文件以.h
为后缀,而C语言代码文件以.c
为后缀,它们都是文本文件,没有本质上的区别,#include
命令的作用也仅仅是将头文件中的文本复制到当前文件,然后和当前文件一起编译。你可以尝试将头文件中的内容复制到当前文件,那样也可以不引入头文件。
.h
中代码的语法规则和.c
中是一样的,你也可以#include <xxx.c>
,这是完全正确的。不过实际开发中没有人会这样做,这样看起来非常不专业,也不规范。
较早的C语言标准库包含了15个头文件,stdio.h
和 stdlib.h
是最常用的两个:
stdio
是 standard input output 的缩写,stdio.h
被称为“标准输入输出文件”,包含的函数大都和输入输出有关,puts()
就是其中之一。stdlib
是 standard library 的缩写,stdlib.h
被称为“标准库文件”,包含的函数比较杂乱,多是一些通用工具型函数,system()
就是其中之一。最后的总结
初学编程,有很多基本概念需要了解,本节就涉及到很多,建议大家把上面的内容多读几遍,必将有所收获。
本节开头的示例是一个C语言程序的基本结构,我们不妨整理一下思路,从整体上再分析一遍:
1) 第1行引入头文件stdio.h
,这是编程中最常用的一个头文件。头文件不是必须要引入的,我们用到了 puts
函数,所以才引入stdio.h
。例如下面的代码完全正确:
int main()
{
return 0;
}
我们没有调用任何函数,所以不必引入头文件。
2) 第2行开始定义主函数main
。main
是程序的入口函数,一个C程序必须有main
函数,而且只能有一个。
3) 第4行调用puts
函数向显示器输出字符串。
4) 第5行是main
函数的返回值。程序运行正确一般返回 0。
2.14 C语言代码中的空白符
空格、制表符、换行符等统称为空白符(space character),它们只用来占位,并没有实际的内容,也显示不出具体的字符。
制表符分为水平制表符和垂直制表符,它们的 ASCII 编码值分别是 9 和 11。
- 垂直制表符在现代计算机中基本不再使用了,也没法在键盘上直接输入,它已经被换行符取代了。
- 水平制表符相当于四个空格,对于大部分编辑器,按下 Tab 键默认就是输入一个水平制表符;如果你进行了个性化设置,按下 Tab 键也可能会输入四个或者两个空格。
对于编译器,有的空白符会被忽略,有的却不能。请看下面几种 puts 的写法:
#include<stdio.h>
int main()
{
puts("C语言");
puts("中文网");
puts
("C语言中文网");
puts
(
"C语言中文网"
)
;
puts ("C语言中文网");
puts ( "C语言中文网" ) ;
return 0;
}
运行结果:
看到输出结果,说明代码没有错误,以上几种 puts 的用法是正确的。puts
和()
之间、" "
和()
之间可以有任意的空白符,它们会被编译器忽略,编译器不认为它们是代码的一部分,它们的存在只是在编辑器中呈现一定的格式,让程序员阅读方便。
需要注意的是,由" "
包围起来的字符串中的空白符不会被忽略,它们会被原样输出到控制台上;并且字符串中间不能换行,否则会产生编译错误。请看下面的代码:
#include<stdio.h>
int main()
{
puts("C语 言 中文网");
puts("C语言
中文网");
return 0;
}
第 5~6 行代码是错误的,字符串必须在一行内结束,不能换行。把这两行代码删除,运行结果为:
程序员要善于利用空白符:缩进(制表符)和换行可以让代码结构更加清晰,空格可以让代码看起来不那么拥挤。专业的程序员同样追求专业的代码格式,大家在以后的学习中可以慢慢体会。