参考资料:高教版《全国计算机等级考试二级教程 C语言程序设计》、《21天学通C语言》
简单的C语言程序的构成和格式
例2.1(对原程序的注释做了一点点修改):
#include <stdio.h>
main()
{
double a, b, area;
/*将矩形的两条长边分别赋给a和b*/
a = 1.2;
b = 3.6;
area = a * b; //计算矩形的面积并存储到变量area中
printf("a = %f, b = %f, area = %f \n", a, b, area) ; //输出矩形的两条长边和面积
}
以上程序中,main是主函数名,C语言规定必须用main作为主函数名。函数是一段执行某项任务的程序代码。在最简单的情况下,main()函数由函数名main,其后一对圆括号(其中包含void)和一对花括号{}组成。在大多数编译器中,省略圆括号中的void不影响程序的运行(但是,ANSI标准规定应该在圆括号中写上void,以表示没有给main函数发送任何消息)。
每一个C程序都必须有一个且只能有一个主函数。一个C程序总是从主函数开始运行。
用一对花括号括起来的部分称为函数体。函数体内通常有定义(说明)部分和执行语句部分。执行部分的语句称为可执行语句,必须放在定义部分之后。C程序的每一条定义语句和执行语句都必须用分号“;”结束。
程序中的#include指令通常称为命令行,必须用“#”号开头,行尾不加分号,它不是C程序的语句。#include指令命令C编译器,在编译时将包含文件的内容添加进程序中。包含文件是独立的磁盘文件,内含程序或编译器要使用的信息。这些包含文件(也称头文件)由编译器提供,所有包含文件的扩展名都是.h。
在例2.1中,#include指令被解释为“添加stdio.h文件的内容”。
在编写程序时,可以在程序中加入注释,以说明变量的含义、语句的作用和程序段的功能,从而帮助人们阅读和理解程序。
程序中以/*开始,以*/结尾的部分,或者以//开始的单独一行都称为注释。编译器会忽略所有的注释。第一种风格可以写成多行(跨行),第二种风格只用于单行注释。
注意:注释不能嵌套。
标识符,常量和变量
标识符
在C语言中,有许多符号(如变量名,函数名,数组名等),都必须遵守一定的规则,按此规则命名的符号称为标识符。
合法标识符的命名规则是:标识符可由字母,数字或下划线组成,并且第一个字母必须为字母或下划线。
在C语言的标识符中,大写字母和小写字母被认为是两个不同的字符。
对于标识符的长度,C语言的编译系统是有规定的,一般为31个字符(实际上可能会更长,但是编译器只会查看前31个字符)。
C语言的标识符可以分为以下三类:
关键字
C语言已经预先规定了一批标识符,它们在程序中都代表着固定的含义,这些标识符称为关键字。例如,用来说明变量类型的int,double以及if语句中的else等都已有了专门的用途,不能再用作变量名或函数名。
预定义标识符
所谓预定义标识符是指在C语言中预先定义并具有特殊含义的标识符,如C语言提供的库函数名(如printf)和预编译处理命令(如define)等。C语言允许把这类标识符重新定义另作他用,但这将使这些标识符失去预先定义的原意。
用户标识符
由用户根据需要定义的标识符称为用户标识符,又称自定义标识符。用户标识符一般用来给变量、函数、数组等命名。
常量
所谓常量是指在程序运行过程中,其值不能被改变的量。在C语言中,有字面常量和符号常量两种类型的常量,它们分别有特殊的用途。
字面常量
字面常量是根据需要直接键入源代码中的值。下面是字面常量的两个示例:
int count = 20;
float tax_rate = 0.28;
20和0.28都是字面常量,分别储存在count和tax_rate中。是否有小数点决定了是整型常量还是浮点型常量。小数点导致C编译器将该常量视为双精度数,如果没有小数点,C编译器将其视为整型常量。
整型常量可以用十进制,八进制,十六进制等形式来表示。
十进制基本常量用一串连续的数字来表示,例如32767,-32768,0等。
八进制数也是用一串连续的数字表示,但其开头必须为数字0,例如010,011,016等是合法的八进制数,018不是合法的八进制数。
十六进制数用数字0和字母x(或X)开头,如0x10,0xde,0xf等都是合法的16进制数。十六进制数中的字母a,b,c,d,e,f既可以用小写也可以用大写。
符号常量
在C语言中,可以用一个符号名来代表一个常量,称为符号常量。这个符号名必须在程序中进行特别的“指定”,并符合标识符的命名规则。
符号常量的值只需要输入一次,在首次定义它时完成。
定义符号常量
C语言有两种方法定义符号常量:#define指令和const关键字。#define指令的格式如下:
#define CONSTNAME literal
以上代码创建了一个名为CONSTNAME,值为literal的符号常量。按照惯例,符号常量名中所有字母都要大写,这样做很容易区分常量名和变量名(都是小写)。
define的工作原理
例2.2 计算圆的面积(把原程序的注释改了一下风格,因为自己比较习惯用这个风格的注释):
#include <stdio.h>
#define PI 3.14159 //定义了一个常量PI
main()
{
double r, s;
r = 5.0;
s = PI * r * r;
printf("s = %f \n", s);
}
程序中用#define命令行定义PI代表一串字符3.14159。#define的工作原理是,在对程序进行编译时,凡是本程序中出现PI的地方,编译程序均用3.14159进行代替。注意,#define不会替换名称、双引号或程序注释中与常量名相同的部分。
用const关键字定义符号常量
从严格意义上来说,用const关键字定义的符号常量实质是变量。const是一个修饰符,可应用于任何变量声明之前。在程序执行期间,不能修改用const声明的变量。下面是const使用的示例:
const int count = 100;
const float pi = 3.14159;
const long debt = 12000000, float tax_rate = 0.21;
const影响本行声明的所有变量。
如果要在程序中修改const变量,编译器会给出一条错误消息。
变量
所谓变量是指在程序运行过程中其值可以改变的量。一个变量实质上是代表了内存中的若干个存储单元。
C语言规定,所有的变量都必须先定义后使用。对变量的定义通常放在函数体内的前部,但也可以放在函数的外部或复合语句的开头。
数值类型
C语言提供多种不同类型的数值变量,不同类型的数值需要不同的内存空间,而且不同类型数值的数学运算也有所不同。
C语言的数值变量包含以下两大类:
- 整型变量,储存没有小数部分的值。
- 实型变量(浮点型变量),储存带有小数部分的值。
上述两大类又包含两种或多种指定的变量类型。
变量类型 | 关键字 | 所需内存(字节) | 取值范围 |
---|---|---|---|
字符 | char | 1 | -128~127 |
短整型 | short | 2 | -32768~32767 |
整形 | int | 4 | -2147483648~214738647 |
长整型 | long | 4 | --2147483648~214738647 |
长长整型 | long long | 8 | -9223372036854775808~9223372036854775807 |
无符号字符 | unsigned char | 1 | 0~255 |
无符号短整型 | unsigned short | 2 | 0~65535 |
无符号整型 | unsigned int | 4 | 0~4292967295 |
无符号长整型 | unsigned long | 4 | 0~4292967295 |
无符号长长整型 | unsigned long long | 8 | 0~18446744073709551615 |
单精度浮点型 | float | 4 | 1.2E-38~3.4E38 |
双精度浮点型 | double | 8 | 2.2E-308~1.8E308 |
虽然数据类型的大小依不同的计算机平台而异,但是C语言保证在不同平台下这5条规则不变:
- char的大小是1字节。
- short的大小不超过(小于或等于)int的大小。
- int的大小不超过long的大小。
- unsigned的大小与int的大小相等。
- float的大小不超过doube的大小。
整数在内存中的存储形式
内存储器的最小存储单位称为位(bit),由于只能存放0或1,因此称为二进制位。
大多数计算机把8个二进制位组成一个字节(byte),并给每一个字节分配一个地址。
若干个字节组成一个字(word),用一个字来存放一条机器指令或一个数据。
通常把一个字节中的最右边一位称为最低位,最左边一位称为最高位。
对于一个有符号整数,其中最高位用来存放整数的符号,称为符号位。若是正整数,最高位放置0;若是负整数,最高位放置1。
变量声明
在C程序中,要先声明变量才能使用。变量声明的格式如下:
typename varname;
typename指定变量类型,varname指定变量名。可以在一行声明多个变量,各变量之间用逗号隔开。如:
int count, number, start;
typedef关键字
typedef关键字用于为已存在的数据类型创建新的名称。实际上,typedef创建了一个别名。例如:
typedef int integer;
这条语句为int创建了一个别名integer。在随后的程序中,可以用integer来定义int类型的变量。
初始化变量
在使用变量前,应该用已知的值初始化它,也可以在定义变量后,通过赋值表达式语句来初始化变量。
如:
int count; //为count留出存储空间
count = 0; //将0储存在count中
int count = 0; //在声明变量的同时初始化它
注意,初始化变量的值不能超过该变量类型的取值范围。
算术表达式
基本的算术运算符
在C语言中,基本的算术运算符是:+、-、*、/、%,分别为加,减,乘,除,求余。这些运算符需要两个运算对象,称为双目运算符。
注1:求余运算符的运算对象只能是整形,在%运算符的左侧是被除数,右侧是除数。
注2:+和-也可用作单目运算符,运算符必须出现在运算数的左边。运算数可以为整形,也可以为实型。
运算符的优先级、结合性和算术表达式
算术运算符的优先级
从左到右优先级降低:
( )、+(单目)、-(单目)、*、/、%、+、-
算术运算符和圆括号的结合性
以上所列的运算符中,只有单目运算符+和-的结合性是从右到左的,其余运算符的结合性都是从左到右。
算术表达式
用算术运算符和一对圆括号将运算数(或称操作数)连接起来的、符合C语言语法的表达式称为算术表达式。
算术表达式中,运算对象可以是常量、变量和函数等。如:
2+sqrt(c)*b;
强制类型转换表达式
强制类型转换表达式的形式如下:
(类型名) (表达式);
(类型名)称为强制类型转换运算符。
利用强制类型转换运算符可以将一个表达式的值转换为指定的类型。例如,表达式(double)(10 % 3)把10%3所得结果1转换成双精度数。
赋值表达式
赋值运算符和赋值表达式
赋值运算符是一个等号(=)。
在赋值表达式语句中,运算符的右侧可以是任意表达式,而左侧必须是一个变量名。因此,赋值的格式是:
变量 = 表达式
执行该语句时,将对表达式求值,并将结果赋值给变量。
复合赋值表达式
在赋值运算符之前加上其他运算符可以构成复合赋值运算符。C语言规定可以使用10种复合赋值运算符,其中与算术运算有关的复合赋值运算符有:+=,-=,*=,/=,%=(两个符号间不能有空格)。复合赋值运算符的优先级与赋值运算符的优先级相同。
赋值运算中的类型转换
在赋值运算中,只有在赋值号右侧表达式的类型与左侧变量类型完全一致时,赋值操作才能进行。
在C语言的表达式(不包括赋值表达式)中,如果运算符两边的整数类型不相同,将进行类型之间的转换,规则如下:
- 一个是短整型,一个是长整型,则短整型转长整型。
- 一个有符号整型,一个无符号整型,则有符号整形转无符号整型。
在C语言的赋值表达式中,赋值号右边的值先转换成与赋值号左边的变量相同的类型,然后进行赋值。应当注意:
- 赋值号左边是短整型,右边是长整型时,短整型变量只能接受长整型数低位上两个字节中的数据,高位上两个字节的数据将丢失。
- 当赋值号左边的变量为无符号整型,右边的值为有符号整形时,则把内存中的内容原样复制,右边数值的范围不应超过左边变量可以接受的数值范围。这时负整数将转换为正数。
- 当赋值号左边的变量为有符号整型,右边的值为无符号整型时,复制机理同上。若符号位为1,将按负数处理。
自加、自减运算符和逗号运算符
自加运算符“++”和自减运算符“--”
- 自加运算符“++”和自减运算符“--”的运算结果是使运算对象的值增1或减1。i++相当于i = i + 1,i--相当于i = i - 1。
- 自加、自减运算符是单目运算符,运算对象可以是整型变量也可以是实型变量,但不能是常量或表达式。
- 自加、自减运算符可以放在运算对象的前面,也可以放在后面。如i++,++i,i--,--i都是合法的。但是,在表达式中放在前面或后面可能有不同的值。
- 自加、自减运算符的结合方向是自右至左。
- 不要在一个表达式中对同一个变量进行多次诸如i++或i--等运算,在不同的编译系统里可能会有不同的结果。
逗号运算和逗号表达式
逗号“,”是C语言提供的一种特殊运算符,用逗号将表达式连接起来的式子称为逗号表达式。逗号的作用是将两个子表达式组成一个表达式。规则如下:
- 两个表达式都会被计算,先计算逗号左边的表达式。
- 整个表达式的结果是右边表达式的值。
- 在所有运算符中,逗号运算符的优先级最低。
例如,下面的语句将b的值赋给x,然后递增a,接着再递增b:
x = (a++, b++);
又如,在这个逗号表达式中,y的值(也就是这个逗号表达式的值)是10,i的值为5:
y =( i = 3, i++, ++i, i + 5);