【Tutorial C】02 快速入门
在信息化、智能化的世界里,可能很早很早 我们就听过许多IT类的名词,
C语言也在其中,我们侃侃而谈,到底C程序是什么样子?
让我们先看简单的一个例子:
#include<stdio.h> /*引入头文件*/ int main(void) /*一个简单的C程序*/ { int number; /*定义个名字叫做number的变量*/ number=2014; /*给number赋一个值*/ printf("Hello ! I am dotcpp.com\n"); /*调用printf()函数*/ printf("This year is %d\n",number); return 0; }
这个简单的程序作用是向屏幕上输出两句话,
如果想看到实际的运行结果的话,我们需要使用编译器编译这段代码然后运行最后的可执行程序,
如果顺利话,将看到运行结果为:
怎么样?一切如我们所预料吧?
可是...为什么...
也许您还有很多个疑问,很多个为什么,比如什么头文件、main、int、\n、%d都是什么东西?都是干什么用的?
以及您可能感觉为什么写的这么奇怪?
不用着急~ 好,让我们一起先来大致看一遍。
#include<stdio.h> /* 包含另一个文件 */
本行代码将告诉编译器引入一个stdio.h的文件(就像我们电脑中的123.txt一样)的全部内容。
stdio.h文件是所有C语言编译器的标准部分,用来提供输入和输出的支持。
int main(void) /*主函数*/
C程序规定一个程序中有一个或多个函数,他们是C程序的基本模块。
但必须有且只有一个main函数。
因为C程序的执行将从main函数开始,到main函数结束而停止。
再回头看看我们的这个简单实例吧,他只有一个名为main的函数,名字后面的圆括号()表明main()是一个函数的名字,括号里面的void表示空的,这里指不接受任何参数。
而前面的int表示main()这个函数在执行完成后返回一个整数(int表示整数,即英文integer的缩写)。
有关更详细的知识,我们会在后面进入更深入的讲解。
而此时,我们只需要把int和void看作是用来定义main()函数的标准即可。
这不是代码,是一句注释,符号/*和*/中包含的话不被编译器编译处理,
而是给我们看的,帮助我们理解程序,你可以认为是笔记~
/*一个简单的C程序*/
这个开始花括号标志着函数的开始,而后面的结束花括号}则标志着函数的结束。
{ //这是括号
这个语句表明告诉编译器,我们将使用一个叫做number的变量,并且它是int(整数)类型。
给number这个变量赋值为2014。
int number; number=2014;
这是一个函数调用语句,在屏幕上显示“Hello ! I am dotcpp.com”,\n表示让光标另起一行。
这里的printf()是C标准库里的一部分。
用术语来讲,它是一个函数。
在一个程序中使用另一个函数(如我们在main()函数当中调用了printf()函数),术语称之为调用了一个函数。
printf("Hello ! I am dotcpp.com\n");
又是一个函数调用语句。
但不同的是并不是输出“This years is %d”换行,
而是输出"This year is 2014"换行,此刻的%d表示输出number值的位置和形式。
printf("This year is %d\n",number);
C函数可以给它的使用者提供或返回一个数值。
此时 我们只需理解这一句是用来满足C标准的要求而已。
return 0;
结束的花括号,函数名后{ 和 }之间的部分称之为函数体。
}// 这是结尾
好的,这就是我们的第一个简单的C程序以及其简单的介绍,
希望大家好好理解并消化,更详细的讲解我们将会在下节展开!
程序细节
或许您已经看懂了前面的叙述,但又觉得不能够通透。
诚然如此,麻雀虽小,五脏俱全,即使非常简单的一个C程序,也包含着许多的知识,
这一节,我们将从逐条语句出发,去深入探讨程序的背后,如果您能更深的理解这个简单的程序,那么在之后的学习中将更加顺畅自如!
一、头文件
#include<stdio.h>
这个是程序的第一行,作用为在我们的代码中该行所在的位置引入stdio.h这个文件的全部内容,
更简单的说,就像一个粘贴的操作,
而此刻大家应该想到,#include后尖括号<>里的文件也可以是其他头文件,
没错,在今后的学习中,我们会看到更多的#include语句, 其中包含了更多的头文件,这也体现了一种设计思想。
可以方便的在多个程序间共享公用的信息。
#include语句是C预处理器指令(preprocessor directive)的一个例子,这些是编译器在编译代码之前要做的准备工作,称之为预处理(preprocessing)
再来说说stdio.h这个文件,不用觉得奇怪,它和我们平常见到的 123.txt 并无差别,只是后缀名不同而已,
这个名字表示:标准输入输出头文件,正如英文:standard input/output header,它包含了与输入输出相关的函数(比如printf)的信息,
在C语言的世界中,人们称出现在文件顶部的信息集合为头(header),C实现通常都带有多个头文件。
那么,为什么C语言没有内置的输入输出语句呢?
一个答案是并非所有的程序都要用到I/O(输入/输出)包,并且C语言的一个基本的设计原则就是避免不必要的成分。
这个经济的使用资源的原则使得C语言在嵌入式编程中非常的流行,
例如,为一个控制自动报警系统的芯片编写程序。
值得一提的是,#include甚至不是C语言的语句!开头的#,这个符号表明这一行是在编译器接手之前先由C预处理器处理的语句。
以后我们将碰到更多的预处理指令。
二、主函数
int main()
接下来的代码声明了一个main函数。
的确,main是一个及其普通的名字,但它是唯一的选择。
一个C程序(我们不考虑例外的情况)总是从main()函数开始执行。
我们可以对自己使用的其他函数任意命名,但是main()必须是开始的函数。每个C程序中必须有它!
那么圆括号的功能呢?
它表明main()是一个函数。以后,我们将遇到更多的函数。现在,请记住这个函数就是C程序的基本模块。
int指明main()函数的返回类型。这意味着main()函数返回值的基本类型为整数。
返回到哪里呢?返回给操作系统。
为什么要有返回值呢?打个比方,就像皇上交代大臣去办事,大臣完成后总要复命,向皇上禀告,告诉皇上是成功还是失败。
函数名后面的圆括号一般包含传递给函数的信息。
在我们这个简单的例子中没有传递任何信息,因此圆括号内包含了单词void。以后我们将看到更多传递参数的例子。
另外,您可能在一些教材或老的版本中,看到过这样的写法:
main()
这种形式在C90标准中勉强允许这种形式,在C99标准不允许。即使您的编译器允许。
以及还有这样的写法:
void main()
仅仅有些编译器允许这种形式,但还没有任何编译器考虑接受它,而有的编译器则会报错。
因此,我们建议您不要这样做。
另一方面,坚持使用标准形式,我们也不必担心程序从一个编译环境移到另一个编译环境上时出错的问题。
三、注释
/*一个简单的C程序*/
包含在/* */之间的部分是程序注释。
使用注释的目的是使人们(包括我们自己)更容易的理解我们的程序。
比如,有些程序员除了用注释说明我们的代码以外,还会在代码的注释中写这一天的天气如何、心情如何等等。
C语言的注释的一个好处就是可以放在任何地方,甚至是和它要解释的语句在同一行。
一个较长的注释可以单放一行,或者是多行。
在/*和*/之间的所有内容都会被编译器忽略掉。
如:
int number ;/* 定义一个整形变量number*/
注释也可以分成两行或多行
/* 笔者自述: 时间:18:24 地点:北半球 天气:窗外天气不明 微冷 肚子有点饿 */
除此之外,C99还增加另一种风格的注释,它被普遍用在C++或java里,这种新形式使用//符号,但这种注释被限制在一行里:
x=10;//将x赋值为10
四、花括号
{ /*... */ }
在C程序中,通常所有的C函数都使用花括号来表示函数体的开始与结束。
它们的存在是必不可少的,因此我们不能丢掉它们。
并且仅有花括号{}能起到这种作用,小括号()和中括号[]都不行。
花括号还可以用来把函数中的语句聚集到一个单元或代码块中。
五、声明
int number;
程序中这一行叫做声明语句(declaration statement)。该声明语句是C语言中最重要的功能之一。
这个特殊的例子声明两件事情。
第一,在函数中您有一个名为num的变量,第二,int说明num是一个整数,也就是说这个数没有小数部分(int是C语言的一种数据类型)。
编译器使用这个信息为变量num在内存中分配一个合适的存储空间。
句末的分号指明这一行是C语言的一个语句或指令,分号是语句的一部分,每个C语言都以一个分号结束。
单词int是C语言的一个关键字,代表了一种C语言的数据类型。关键字是用来表达语言的单词,您不能将他们用于其他目的。
比如,不能用int用作一个函数名或者一个变量的名字。
本例中的单词num是一个标识符(identifier),也就是您为一个变量、函数或其他实体所选的名字。这样该声明就把一个特殊的标识符和计算机中的一个特殊位置联系了起来,同时也确定了该位置存储的信息类型(即数据类型),我们为这个变量赋值,也就相当于在计算机中这个特殊的位置(今后我们将清楚,这个位置即所谓的地址)赋值。
因为,C语言是人和计算机沟通的纽带。
在C语言中,所有变量都必须在使用之前定义。这就意味着您必须提供程序中要用到的所有变量名的列表,并且指出每个变量的数据类型。
声明变量被认为是一种好的编程技术,在C语言当中必须这样做。
传统上,C语言要求必须在一个代码块的开始处声明变量,在这之前不允许任何其他语句。
也就是说,main()函数如下所示:
int main()//traditional rules (传统的用法) { int year; int month; int day; year = 2014; month = 2; day = 28; //other statements (其他的语句) }
C99遵循 C++的惯例,允许把声明放在代码块中的任何位置。
然而,在首次使用变量之前仍然必须先声明它。
因此,如果你的编译器支持这种功能,你的代码就可以像下面这样:
int main() // C99 rules (C99 用法) { // some statements (一些语句) int doors; doors = 5; // first use of doors (第一次使用到的变量) // more statements (更多的语句) int dogs; dogs = 3; // first use of dogs (第一次使用到的变量) // other statements (其他的语句) }
现在你可能还有三个问题。
首先,数据类型是什么?
第二,可以选择什么样的名字?
第三,为什么必须对变量进行声明?
下面来看这些问题的答案。
1.数据类型
C语言可以处理多个数据种类(或类型),例如整数,字符和浮点数。
把一个变量声明为整数类型或字符类型是计算机正确地存储,获取和解释该数据的基本前提。
在后面您将学到各种各样的可用类型。
2.名字的选择
您应该尽量使用有意义的变量名(例如,如果你的程序需要苹果这个变量,那么使用apple)。
如果名字不能表达清楚,可以用注释解释变量所代表的意思。
通过这种方式使程序更易读是良好编程的基本技巧之一。
能够使用的字符的数量与 C语言的不同实现有关。
C99标准允许一个标识符最多可以有 63个字符,除了外部标识符,后者只识别31个字符。
与C90分别要求的31个字符和6个字符相比较,这是一个相当可观的进步,而更旧的编译器通常最多只允许8个字符。
实际上,你使用的字符数量可以超过规定的最大值,但是编译器不会识别额外的字符。
因此,如果一个系统最大字符数为8,那么clangdot和clangdotcc将被看作是一个名字,因为它们的前8个字符相同。
可供使用的字符有小写字母,大写字母,数字和下划线。第一个字符必须是字母或者下划线。
C语言的名字是区分大小写的,即把一个大写字母和与之对应的小写字母看作是不同的。
因此,clang不同于Clang或者CLANG。
六. 赋值
number =1;
这行程序是一个赋值语句(assignment statement)。
赋值语句是 C语言的基本操作之一。
这个特殊的例子的意思是“把值1赋给变量 num”。
前面的 int num;语句在计算机内存中为变量 num 分配了空间,该赋值语句在那个地方为变量存储了一个值。
如果你想的话,以后你还可以给 num 赋另一个值,这就是把 num 称为变量的原因。
可以把变量理解成是一个容器,用来盛放常量的。
另外注意赋值语句赋值的顺序是从右到左。同样,该语句也用分号结束。
七、printf()函数
printf ("Hello!"); printf ("I am dotcpp.com\n"); printf ("My birthday is %d\n", num);
所有这些行都使用了 C语言的一个标准函数:printf()。
圆括号表明 printf 是一个函数名。圆括号中包含的内容是从函数 main()传递到函数 printf()的信息。
例如,第一行把 Hello! 传递给 printf()函数。 这样的信息被称为参数(argument),更完整的名称是函数的实际参数(actual argument)。
printf()函数如何处理这个参数?程序将识别两个双引号之间的内容并把它们显示在屏幕上。
第一行 printf()语句是如何在 C语言中调用(call)或请求(invoke)一个函数的例子。
只须键入函数的名字,把所需的一个或多个参数放进圆括号中。
当程序运行到这一行时,控制权将转给该函数(在这个例子中是 printf())。
当函数完成了它所要做的工作,将控制权返回给原来的函数(调用函数),在这个例子中是 main()。
那么下一个 printf()行呢?引号中有字符\n,但并没有输出它们!发生了什么事情呢?
\n字符的意思是开始新的一行。
\n 组合(依次键入这两个字符)代表一个称为换行符(newline character)的字符,它意味着“在下一行的最左边开始新的一行”。
换句话说,打印换行字符的效果和在普通键盘上按下回车键一样。
当键入 printf()这个参数时,为什么不直接按回车键呢?因为那将看作是直接针对编辑器的命令,而不是作为存在源代码中的指令。
也就是说,当你按回车键时,编辑器退出你正在输入的当前行,并开始新的一行。而换行符则影响程序的输出如何显示。
换行符是转义字符(Escape Sequence)的一个例子。
转义字符通常用于代表难于表达的或是无法键入的字符。
其他的例子比如 \t 代表 Tab键, \b 代表退格键盘。每个转义字符都用斜线字符(\)开始。
这样就解释了三个 printf()语句只产生两行输出的原因:
第一个 printf指令中没有换行字符,而第二个和第三个都有。
最后一个 printf()行中又有一个奇怪的问题:当输出这一行时 %d 起什么作用?
回忆一下,这一行的输出结果是:
My birthday is 2014
喔!当这一行输出时,数字2014被符号组合%d代替了,而1是变量 num的值。
%d是一个占位符,其作用是指出输出 num 值的位置。
事实上,%告诉程序把一个变量在这个位置输出,d告诉程序将输出一个十进制(以10为基数)整数变量。
printf()函数允许多种输出变量格式,包括十六进制(以16为基数)整数和带小数点的数。
实际上,printf()中的 f 暗示着这是一种格式化(format)的输出函数。
每一种数据都有自己的说明符,往后会有更多的说明。
八. Return 语句
return 0;
return 语句(返回语句)是程序的最后一个语句。
在 int main(void)中 int 表示 main()函数的返回值应该是一个整数。
C标准要求 main()这样做。
带有返回值的 C语言函数要使用一个 return 语句,该语句包括关键字 return,后面紧跟着要返回的值,然后是一个分号。
对于 main()函数来说,如果你漏掉了 return语句,则大多数编译器将对你的疏忽提出警告,但仍将编译该程序。
此时,你可以暂时把 main()中的 return语句看作是保持逻辑连贯性所需的内容。
但对于某些操作系统(包括 DOS 和 UNIX )而言,它有实际的用途。
通过前面的一个简单的C程序例子,相信您已经对C程序有了一个比较好的理解,
正如前面您看到的程序一样,每一个基本的程序都会有这么一个框架,这是一个C程序的基本格式,不然是无法编译通过的。
包括今后出现的程序样例,您都要这么做,我们推荐您使用GCC编译器,因为它的编译要求更接近C99标准。
当然您也可以在Windows系统下使用VC6、CodeBlocks、DevC++等等都可以。
关于C标准:
也许您经常听人们谈论C89、C90、C99之类的名字而不知道是什么东西。
简单来说,这些就是ANSI(美国国家标准局)不同年份制定的不同的国际标准,C99就是1999年制定,C90就是1990年制定,而C89就是1989年制定的咯。
很明显C99要比C89要新很多,主要体现在支持了很多数据类型和新特性。
为了使读者更容易入门,本教程不过多的提及这些新特性。
一些建议:
在学习过程中,每章的程序都强烈建议您亲自上机编译测试,并建议您尝试着修改程序来体验程序每一处的作用,以这种方式加深对程序的理解。
同时,我们强烈推荐您掌握不同编译器的断点调试功能,
不要过分依赖printf()语句的输出结果,而要知道程序的逐条语句的执行流程,这样可以帮助您更好的了解程序。
原文:https://www.dotcpp.com/course/5