【C primer plus 笔记】 第二章 C语言概述
2.1 简单的C程序示例
#include <stdio.h> int main(void) /* 一个简单的C程序 */ { int num; /* 定义一个名为num的变量 */ num = 1; /* 为num赋一个值 */ printf("I am a simple "); /* 使用printf()函数 */ printf("computer.\n"); printf("My favorite number is %d because it is first.\n", num); return 0; }

2.2 示例解释
#include ←包含另一个文件
该行告诉编译器把stdio.h中的内容包含在当前程序中。stdio.h是C编译器软件包的标准部分,它提供键盘输入和屏幕输出的支持。
该行的作用相当于把stdio.h文件中的所有内容都输入改行所在的位置,实际上,这是一种“拷贝-粘贴”的操作。include文件提供了一种方便的途径共享许多程序共有的信息
#include这行代码是一条C预处理器命令,通常,C编译器在编译前会对源代码做一些准备工作,即预处理。
所有的C编译器软件包都提供stdio,h文件,该文件中包含了供编译器使用的输入和输出函数信息,该文件名的含义是标准输入/输出头文件。通常,在C程序顶部的信息集合被称为头文件。
在大多数情况下,头文件包含了编译器创建最终可执行程序要用到的信息。例如,头文件中可以定义一些常量,或者指明函数名以及如何使用它们,但是,函数的实际代码在一个预编译代码的库文件中,简而言之,头文件帮助编译器把程序正确地组合在一起。
int main(void) ←函数名
C程序一定从main()函数开始执行,除了main()函数,可以任意命名其他函数,而且main()函数必须是开始的函数,圆括号用于识别main()是一个函数。
int是main()函数的返回类型,这表明main()函数返回的值是整数,返回给操作系统。
通常,函数名后面的圆括号中包含一些传入函数的信息,该例中没有传递任何信息,因此,圆括号内是单词void
/* 一个简单的C程序 *//* 定义一个名为num的变量 *//* 为num赋一个值 *//* 使用printf()函数 */ ←注释
在程序中,被/**/两个符号括起来的部分是程序的注释,写注释能让他人包括自己更容易明白所写的程序。C语言主食的好处之一是,可将注释放在任意的地方,甚至是与要解释的内容放在同一行,较长的注释可单独放一行或多行。在/*和*/之间的内容都会被编译器忽略。
C99新增了另一种风格的注释,这种风格使用//符号创建注释,仅限于单行。
因为一行末尾就标志着注释的结束,所以这种风格的注释只需要在注释开始处表明//符号即可。这种新形式的注释是为了解决旧形式注释存在的潜在“消失代码”的问题。
{} ←函数体开始、结束
程序中,花括号把main()函数括起来,一般而言,所有的C函数都使用花括号标记函数体的开始和结束。这是规定,不能省略。只有花括号能起这种作用。花括号还可用于把函数中的多条语句合并为一个单元或块。
int num; ←声明
这行代码叫作声明。声明是C语言最重要的特性之一。
int是一种数据类型,编译器使用这些信息为num变量在内存中分配存储空间,分号在C语言中是大部分语句和声明的一部分。
int是C语言的一个关键字,表示一种基本的C语言数据类型。关键字是语言定义的单词,不能做其他用途。例如,不能用int作为函数名和变量名。
num是一个标识符,也就是一个变量、函数或其他实体的名称。因此,声明把特定标识符与计算机内部中的特定位置联系起来,同时也确定了存储在某位置的信息类型或数据类型。
在C语言中,所有变量都必须先声明才能使用。
数据类型:
C语言可以处理多种类型的数据,如整数、字符和浮点数。把变量声明为整型或字符型,计算机才能正确的储存、读取和解释数据。
命名:
给变量命名时要使用有意义的变量名或标识符,如果变量名无法清楚地表达自身的用途,可以在注释中进一步说明
可以用小写字母、大写字母、数字和下划线来命名,而且,名称的第一个字符必须是字符或下划线,不能是数字
操作系统等使用一个或两个下划线开始的标识符,所以最好避免使用这种名称
C语言的名称区分大小写,即把一个字母的大写和小写视为两个不同的字符
声明变量的四个理由:
-
把所有的变量放在一处,方便读者查找和理解程序的用途
-
声明变量会促使你在编写程序之前做一些计划
-
声明变量有助于发现隐藏在程序中的小错误
-
如果事先未声明变量,C程序将无法通过编译
num = 1; ←赋值表达式语句
这行代码是赋值表达式语句。赋值是C语言的基本操作之一,该行代码的意思是“把值1赋给变量num”。
在执行int num;声明时,编译器在计算机内存中为变量num预留了空间,然后在执行这行赋值表达式语句时,把值存储在之前预留的位置,可以给num赋不同的值,这就是num之所以被称为变量的原因。
注意,该赋值表达式语句从右侧把值赋到与左侧。该语句以分号结尾。
printf("I am a simple "); ←调用函数printf("computer.\n"); ←调用另一个函数printf("My favorite number is %d because it is first.\n", num);
接下来调用这个printf()函数在上条语句打印出来的内容后面加上“computer”,代码\n告诉计算机另起一行,即把光标移至下一行
最后调用printf()把num的值内嵌在用双引号括起来的内容中一并打印,%d告诉计算机以何种形式输出num的值,打印在何处
这三行都使用了C语言的一个标准函数:printf(),圆括号表明printf是一个函数名,圆括号中的内容是从main()函数传递给printf()函数的信息,该信息被称为参数,或者更确切地说,是函数的实际参数,
在C语言中,实际参数(简称实参)是传递给函数的特定值,形式参数(简称形参)是函数中用于储存值的变量。
printf()函数会查看双引号中的内容,并将其打印在屏幕上。
第一行printf()演示了在C语言中如何调用函数,只需要输入函数名,把所需的参数填入圆括号即可。当程序运行到这一行时,控制权被转给已命名的函数(printf())。函数执行结束后,控制权被返回至主调函数,该例中是main()。
第二行printf()函数的双引号中的\n字符并未输出。\n组合代表一盒换行符。对于printf()而言,它的意思是“在下一行的最左边开始新的一行”也就是说,打印换行符的效果与在键盘按下enter键相同。但按下enter键,编译器会退出当前行并开始新的一行。而换行符仅会影响程序输出的显示格式
换行符是一个转义序列,转义序列用于代表难以表示或无法输入的字符。如\t代表tab键,\b代表backspace键,每个转义序列都以反斜杠字符(\)开始
%d相当于是一个占位符,起作用是指明输出num值的位置,%提醒程序,要在该处打印一个变量,d表明把变量作为十进制整数打印。printf()函数名中的f提醒用户,这是一种格式化打印函数。
return 0; ←return语句
C函数可以给调用方提供(或返回)一个数。目前,可暂时把该行看作是结束main()函数的要求。
return语句是最后一条语句,int main(void)中的int表明main()函数应返回一个整数,C标准要求main()这样做。有返回值的C函数要有return语句,该语句以return关键字开始,后面是待返回的值,并以分号结尾。如果遗漏main()函数中的return语句,程序在运行至最外面的右花括号时会返回0。因此,可以省略main()函数末尾的return语句。但是,不要在其他有返回值的函数中漏掉他,因此强烈建议在main()函数中保留return语句,在这种情况下,可以将其看做是统一代码风格,但对于某些操作系统,return语句有实际的用途
2.3 简单程序的结构
程序由一个或多个函数组成,必须有main()函数。
函数由函数头和函数体组成,函数头包括函数名、传入该函数的信息类型和函数的返回类型。通过函数名后的圆括号可识别出函数,圆括号里可能为空,可能有参数。函数体被花括号括起来,由一系列语句、声明组成。
简而言之,一个简单的C程序的格式如下:
#include <stdio.h> int main(void) { 语句 return 0; }
2.4 提高程序可读性的技巧
第一条:选择有意义的函数名
第二条:写注释
第三条:在函数中用空行分隔概念上的多个部分
第四条:每条语句各占一行
2.5 进一步使用C
//fathm_ft.c -- 把2音寻转换成英寸 #include <stdio.h> int main(void) { int feet, fathoms; fathoms = 2; feet = 6 * fathoms; printf("There are %d feet in %d fathoms!\n", feet, fathoms); printf("Yes, I said %d feet!\n", 6 * fathoms); return 0; }
程序在开始处有一条注释,给出了文件名和程序的目的。写这种程序说明很简单,不费时,而且在以后浏览或打印程序时很有帮助
多条声明
程序在一条声明中声明了两个变量,而不是一个变量。为此,要在声明中用逗号隔开两个变量。
乘法
然后,程序进行了乘法运算,C语言和许多其他语言一样,用*表示乘法。
打印多个值
最后,程序以新的方式使用printf()函数。
该程序涉及的范围有限,但它是把音寻转换成英寸程序的核心部分,我们还需要把其他值通过交互的方式赋给feet。
2.6 多个函数
//two_func.c -- 一个文件中包含两个函数 #include <stdio.h> void butler(void); //C函数原型 int main(void) { printf("I will summon the butler funtion.\n"); butler(); printf("Yes. Bring me some tea and writeable DVDs.\n"); return 0; } void butler(void) //函数定义开始 { printf("You rang, sir?\n"); }
bulter()函数在程序中出现了3次,第一次是函数原型,告知编译器在程序中要使用该函数,第二次是以函数调用的形式出现在main()中;最后一次出现在函数定义中,函数定义即是函数本身的源代码。
函数原型是一种声明方式,告知编译器正在使用某函数,因此函数原型也被称为函数声明,函数原型还指明了函数的属性,例如,bulter()函数原型中第一个void表明,bulter()函数没有返回值,第二个void的意思是bulter()函数不带参数,因此,当编译器运行至此,会检查bulter()是否使用得当。
在main()中调用bulter()很简单,写出函数名和圆括号即可,当bulter()执行完毕后,程序会继续执行main()中的下一条语句
程序的最后部分是bulter()函数的定义,其形式和main()相同,都包含函数头和用花括号括起来的函数体,函数头重述了函数原型的信息:bulter()不带任何参数,且没有返回值。
C标准建议,要为程序中所有函数提供函数原型。标准include文件为标准库函数提供了函数原型
2.7 调试程序
程序的错误通常叫做bug,找出并修正错误的过程叫做调试
语法错误
如果不遵循C语言的规则就会犯语法错误,这类似于英文中的语法错误。
C语言的语法错误指的是,把有效的C符号放在错误的地方
在编译之前,浏览源代码看是否能发现一些明显的错误,接下来,查看编译器是否发现错误,检查程序的语法错误是它的工作之一。在编译程序时,编译器发现错误会报告错误信息,指出每一处错误的性质和具体位置
尽管如此,编译器也有出错的时候,也许某处隐藏的语法错误会导致编译器误判。实际上,有时不用把编译器报告的所有错误注意修正,仅修正第一条或前几行错误后,错误信息就会少很多。继续这样做,直到编译器不在报错。编译器另一个常见的毛病是,报错的位置可能比真正的错误位置滞后一行。
语义错误
语义错误是指意思上的错误,编译器无法检测语义错误,因为这类错误并未违反C语言的规则。编译器无法了解你的真正意图,所以你只能自己找出这些错误。
方法是把自己想象成计算机,跟着程序的步骤一步一步地执行
通过逐步跟踪程序的执行步骤,并记录每个变量,便可监视程序的状态。
程序状态是在程序的执行过程中,某给定点上所有变量值的集合,它是计算机当前状态的一个快照
定位语义错误的另一种方法是:在程序的关键点插入额外的printf()语句,以监视指定变量值的变化,通常查看值的变化可以了解程序的执行情况,对程序的执行满意后,便可删除额外的printf()语句,然后重新编译
检测程序状态的第三种方法是使用调试器。调试器是一种程序,让你一步一步运行另一个程序,并检查该程序变量的值。调试器有不同的使用难度和复杂度。
2.8 关键字和保留标识符
关键字是C语言的词汇。它们对C而言比较特殊,不能用它们作为标识符,许多关键字用于指定不同的类型,还有一些关键字用于程序中语句的执行程序。
如果使用关键字不当,编译器会将其视为语法错误。还有一些保留标识符,C语言已经指定了它们的用途或保留它们的使用权,如果你使用这些标识符来表示其他意思会导致一些问题。保留标识符包括哪些以下划线开头的标识符和标准库函数名。



浙公网安备 33010602011771号