2.1 简单代码的运
【例 2.1】在屏幕上输出英文短句“Programming is fun.”
/* Output:"Programming is fun."*/ /*注释*/
# include<stdio.h> /*编译预处理命令*/
int main(void)
{
printf("Programming is fun."); /*调用 printf() 函数输出文字*/
return 0;
}
运行结果:
Programming is fun.
说明:
1.程序中的第一行:
/* Outping:"Programming is fun."*/ /*注释*/
它是程序的注释,用于说明程序的功能,是为增加程序的可读性而设置的。注释内容必须包含在/*和*/之间,其内容可以是任何可显示字符,注释部分对程序的编译过程和执行结果没有任何影响。注意“/”和“*”之间不能有空格。
在程序的适当位置插入注释,可以使程序容易被人理解。注释可以出现在程序中任意合适的地方,但必须成对出现。注意注释不能出现在语句的中间。
2.程序中的第二行是
#inciude<stdio.h>
它是编译预处理命令,因为程序中调用了printf()函数,该函数是C语言提供的标准输出函数,在系统文件stdio.h(称为头文件)中声明,所以在程序开始处要使用include将该文件包含起来。注意C语言有效的预处理命令总是以#开始的,预处理命令的末尾不加分号。
3.程序中第三行
int main(void)
它是本程序中的“主函数”,在一个C程序中有且仅有一个main()函数。程序运行时,会首先从main()函数开始执行。该行的关键字int说明main()函数的返回值是整形数,括号中的void表示main函数不需要参数。
4.一对大括号将函数的所有语句括起来,构成了函数体。本程序共有两条语句。第一条语句为:printf("Programming is fun.");
它由函数和分号两部分组成。printf("Programming is fun.")调用了标准输出函数,将引号中的内容原样输出在屏幕上(C语言默认输出设备为屏幕),语句末尾的分号表示语句结束。
注意:C语言中除复合语句外的所有语句都必须以分号结束。
main()函数的第二条语句:
return 0;
它结束main()函数的运行,并向系统返回一个整数0,做为程序的结束状态。若果返回0说明程序正常运行,返回其他值则表示不同的错误情况。
1 #include <stdio.h>
2 int main(void)
3 {
4 printf("Programming is fun.\n");
5 printf("And Programming in C is even more fun!");
6 return 0;
7 }
运行结果为:
Programming is fun
And Programming in c is even more fun!
语句中“\n”是换行符,即在输出“Programming is fun.”后换行。\n称为转义字符。
【例2.2】设球体的半径为r、求体积为v、球表面积为f,求体积和求表面积的计算式如下:
1 #include<stdio.h>
2 #define PI 3.14159
3 void main()
4 {
5 int r;
6 float v, f;
7 r = 2;
8 v = 4.0 * PI * r * r * r / 3.0;
9 f = 4.0 * PI * r * r;
10 printf("体积为:%f,表面积为:%f\n", v, f);
11 }
运行结果为:
体积为:33.510292,表面积为:50.265442
说明:
(1)语程序中第二行语句:“#define PI 3.14159”
定义了一个符号常量 PI,这样程序中凡是需要使用3.14159的地方都可以用PI代替,提高了程序的可读性。
(2)void main()
:main函数前面表示的是程序的返回值类型,后面表示的是传入参数,这里传入参数为空被省略了,返回参数也是空,也可以被省略。
(3)%f
:会将printf引号内除了%f
之外的内容原样输出,并在第一个%f
上输出v的值,在第二个%f 上输出f的值。
注意:printf()函数不但能够输出固定不变的内容,还可以输出变量的值。
2.2 C语言的数据类型
C语言程序中所用到的每一个常量、变量和函数等程序的基本操作对象都有一种数据类型与之相联系。例如2.2中,变量r为整型,变量v和f为单精度浮点型。数据类型决定了取值范围、占用内存的字节数和所能进行的操作。
C语言中可以使用的数据类型如图2.1所示。由图2.1所示,C语言提供了四种基本数据类型

说明:
(1)构造类型是根据已定义的一个或多个数据类型,用构造的方法来定义的。可以理解为,一个构造类型的值由若干个“成员”或“分量”构成。每个“成员”都是一个基本类型或一个构造类型。
(2)指针是C语言中一种特殊的,同时又具有重要作用的数据类型。
2.3 C语言的常量
【概念】常量是指在程序运行的过程中值不能被该变的量,分为直接常量和符号常量。
2.3.1直接常量
直接常量分为整型常量、实型常量、字符型常量和字符串常量。
1. 整型常量
【概念】 整型常量即整数,包括正整数、负整数和零。C语言中,整型常量可以用十进制、八进制、十六进制表示。
- 十进制表示:由数字0~9,正、负号组成,如369,-663;
- 八进制表示:以0(数字0)为前缀,其后由数字0~7组成,八进制数一般是无符号数,如0192、-011为不合法的八进制常量而0163、063都为合法的八进制常量。
- 十六进制表示:以0x或0X为前缀,其后由数字0~9和字母A~F(字母大小写均可)组成,十六进制数一般是无符号数;如0x12cd、0X6Fa等。
2. 实型常量
【概念】 实型常量即实数,又称为浮点数。 C语言中,实数只能用十进制形式表示,实数的
表现形式有两种:小数形式和指数形式。
- 小数形式:由整数部分、小数点和小数部分组成。如12.345,3.,-.123。
- 指数形式:由尾数部分、字母E或e和指数部分组成,格式为:±尾数E指数。如:1.25E-2、3.14E+3,它们的数值分别是
、
。
注意:
(1) 以小数形式表示实数时,必须有小数点,并且小数点的前、后至少一边要有数字。
(2) 以指数形式表示实数时,字母E (或e)的前后必须有数字,并且指数部分只能是整数。如12.-E3、1.5E、E6都是不正确的实数。(3)在C语言中,实型常量默认为是double型的实数,如果在数字后面加字母f或F(如1.65f、654.87F),则认为是float型的实数。
3. 字符型常量
【概念】字符常量指单个字符,用单引号及其括起的字符来表示。如'$'、'?'为合法字符。
特点如下:
- (1) 字符常量只能用单引号括起来,不能用双引号或其它括号。
- (2) 字符常量只能是单个字符,不能是多个字符组成的字符串。
- (3) 字符可以是ASCII字符集中的任意字符。按ASCII码的大小,不同的字符之间存在着次序,以字符的ASCII码值按升序连续排列。
- (4) 对于控制符(如回车、换行等)与不可见字符,在C语言中通过转义字符来表示。转义字符是用'\'开头后面加上一个字符或用八进制、十六进制表示的ASCII码值组成,'\'的作用是改变其后面字母的字符或ASCII码值的原有意义,转义为另外的含义。
常见转义字符
转义字符 | 转义功能 | ASCII码值 |
---|---|---|
\0 | 空字符 | 0 |
\a | 响铃 | 7 |
\b | 退格(Backspace) | 8 |
\t | 水平制表符(横向跳格) | 9 |
\n | 回车换行(Enter) | 10 |
\v | 竖向跳格 | 11 |
\f | 换页 | 12 |
\r | 回车 | 13 |
" | 双引号(”) | 34 |
' | 单引号(’) | 39 |
? | 问号(?) | 63 |
\ | 反斜线字符(\) | 92 |
\ddd | 1~3位八进制所代表的字符 | |
\xhh | 1~2位十六进制所代表的字符 |
【例2.3】 转义字符的使用示例
1 # include<stdeio.h>
2 int main()
3 { char b,c,d,e;
4 b='\43';
5 c='\103';
6 d='\x2a';
7 e='\x41';
8 printf("b=%c,c=%c,d=%c,e=%c\n",b,c,d,e); /*语句1*/
9 printf("\"good\40morning!\b\"!\n"); /*语句2*/
10 printf("\123456"); /*语句2*/
11 return 0;
12 }
运行结果:
b=#,c=C,d=*,e=A
“good morning”!
S456
4. 字符串常量
【概念】字符串常量是由一对双引号''"括起来的零个或多个字符序列,如:"Hello Worl"。字符串中可以使用空格字符、转义字符和其他字符,也可以使用汉字等文字符号字符串中还可以使用空字符,如:" "表示空串,即不包含任何字符。
字符串常量自内存中占用一段连续的存储单元,系统自动在每个字符串尾部加上'\0'作为字符串结束的标志,因此,n个字符组成的字符串,在内存中要占用n+1个字节空间。可以使用sizeof运算符来计算字符串占用内存空间的大小。
如字符串常量"Hello\nWorl"占用12个字节的内存空间,存储图如下:
W | e | l | l | o | \n | W | o | r | l | \0 |
系统自动在每个字符串的尾部加上’\0’作为字符串的结束标志
注意:
- n个字符组成的字符串,在内存中要占用n+1个字节空间
- 可以使用sizeof运算符来计算字符串占用的内存空间大小
- 字符串的长度等于该字符串中所包含的有效字符的个数
- 在字符串中如遇到’\0’则认为该字符串结束
- 如果字符串中有转义字符,则一个转义字符作为一个字符
- 可以使用strlen()函数计算字符串的长度
- 字符常量和字符串常量在内存中的存储情况是不同的
- 如’6’在内存中占1个字节,存储的是其ASCII码
- “6”在内存中占2个字节,一个字节存储’6’,一个字节存储’\0’
2.3.2 符号常量
在C语言中,可以用一个标识符来表示一个常量,称之为符号常量
符号常量在使用之前必须先定义,其一般形式为:
1.#define 标识符 常量值
一个#define命令只能定义一个符号常量,若要定义多个符号常量,需使用多个#define命令
例:某程序需要使用一个代表常数3.145的符号常量名xp,则以下定义中正确的是 。
A.#define xp 3.145;
B.#define xp(3.145)
C.#define xp=3.145
D.#define xp 3.145
答案:D
例:利用符号常量计算价格
1 #include<stdio.h>
2 #define PRICE 20
3 int main()
4 {
5 int num,total;
6 num=10;
7 total=num* PRICE;
8 printf("总价格为:%d\n",total);
9 return 0;
10 }
运行结果:
总价格为:200
2.符号常量的使用,可以为编写程序提供很多好处:
- 增加程序的可读性
- 提高程序的可维护性
- 简化程序代码
- 方便数组的定义
2.4 C语言的变量
在程序的运行过程中,其值可以被改变的量称为变量
变量用于从外部接收数据、保存一些不断变化的值、保存中间结果及最终结果,而这些都无法用常量来实现
2.4.1 变量的定义与使用
1. 变量的定义
[存储类型] 类型说明符 变量名;
- 定义四个静态的整型变量a,b,c,d:
static int a,b,c,d;
- 定义两个字符型变量ch1,ch2:
char ch1,ch2;
- 定义一个单精度浮点数变量f:
float f;
注:
- 类型说明符必须是C语言中的有效数据类型,如int、float、double、char等,用于指定变量的类型,该类型决定了编译时分配给变量的内存单元的多少
- 变量名表可以由一个或多个变量名组成,各变量名之间用“,”分隔。变量名必须是合法的C语言标识符,变量名一般使用小写字母
- 变量的定义必须放在变量的使用之前,一般在函数体的开头部分进行定义
2. 变量的初始化
C语言允许在定义变量的同时对变量赋值,这个过程称为变量的初始化
- 定义一个整型变量x并赋初值为2:
int x=2;
- 定义两个整型变量s和t,分别赋初值为1:
int s=1,t=1;
- 定义一个单精度型变量f并赋初值为3.68:
float f =3.68;
- 定义一个字符型变量ch并赋初值为字符x:
char ch='x';
注:
- 对一个变量赋初值之后,该值被存储在分配给该变量的内存空间中
- 不允许对多个未定义的同类型变量连续初始化
- 初始化时,“=”右边表达式的数据类型和“=”左边的变量的类型如果不一致,系统会进行自动赋值转换
- 没有进行初始化的变量,其值是由定义时所使用的存储类型决定的变量的使用
3.变量的使用
变量应该先赋值,后引用
例:变量使用示例
1 #include<stdio.h>
2 int main()
3 {
4 int a,b,c;
5 char ch='A'; /*初始化*/
6 a=10; /*使用赋值语句对变量a赋初值*/
7 b=a+ch; /*使用赋值语句对变量b赋值*/
8 scanf("%d",&c); /*使用scanf函数对变量c赋值*/
9 printf("%d,%d,%d,%c\n",a,b,c,ch);
10 return 0;
11 }
运行结果:
若程序运行时输入:
10↙
则程序的运行结果如下:
10,75,10,A
2.4.2 整形变量
Visual C++ 2010环境下,各种整型的关键字及占用内存字节数和取值范围如下表:
关键字 | 类型 | 占用字节数 | 取值范围 |
---|---|---|---|
short int | 短整型 | 2 | -32768~32767 |
int | 整型 | 4 | -2147483648~2147483647 |
long int | 长整型 | 4 | -2147483648~2147483647 |
unsigned short | 无符号短整型 | 2 | 0~65535 |
unsigned int | 无符号整型 | 4 | 0~4294964295 |
unsigned long | 无符号长整型 | 4 | 0~4294964295 |
注:
- 各种无符号整数所占的字节数与相应的有符号整数相同。但由于省去了符号位,故不能表示负数。
- 有符号整数以二进制补码形式存储。最左边第1位表示符号,该位为0,表示正数,该位为1,表示负数。
- 无符号整数以二进制原码形式存储。
例:不同类型整型变量的定义与使用示例
1 #include<stdio.h> 2 int main() 3 { 4 int a,b,c,d; 5 unsigned long e; 6 a=5;b=6;e=10; 7 c=a+e; 8 d=b+e; 9 printf("c=%d,d=%d\n",c,d); 10 return 0; 11 }
运行结果:
c=15,d=16
1 #include<stdio.h> 2 int main() 3 { 4 short int a, b; 5 a = 32767; 6 b = a + 10; 7 printf("a=%d, b=%d\n", a, b); 8 return 0; 9 }
运行结果:
a=32767,b=-32768
2.4.3 实型变量
实型的关键字及占用内存字节数和取值范围如表所示:
关键字 | 类型 | 占用字节数 | 取值范围 |
---|---|---|---|
float | 单精度型 | 4 | 3.4E-38~3.4E+38 |
double | 双精度型 | 8 | 1.7E-308~1.7E+308 |
- 单精度型数据能保留7位有效数字
- 双精度型数据能保留16位有效数字
例:实型变量的使用示例 | |
1 #include<stdio.h> 2 int main() 3 { 4 float a=1234.56789; 5 double b=1234.567895678; 6 printf("a=%f,b=%f\n",a,b); 7 return 0; 8 }
运行结果:
a=1234.567871,b=1234.567896
2.4.4 字符型变量
- 字符型变量的值是字符常量,即用单引号引起来的单个字符
- 字符型变量的类型说明符是char,其类型说明的格式和命名规则与整型变量相同
注:
由于字符常量在内存中占用一个字节,用于存储它的ASCII码值
所以C语言中的字符具有数值特征,可以像整数一样参加运算
允许对整型变量赋以字符值,也允许对字符变量赋以整型值。
例:字符变量的使用示例
#include<stdio.h>
int main()
{
char c1,c2;
c1='A';
c2=65;
printf("%c,%c\n",c1,c2);
printf("%d,%d\n",c1,c2);
return 0;
}
运行结果:
A,A
65,65
例:字符变量的使用示例
#include<stdio.h>
int main()
{
char c1,c2;
c1='A';
c2='B';
c1=c1+32;
c2=c2+32;
printf("%c,%c\n",c1,c2);
printf("%d,%d\n",c1,c2);
return 0;
}
运行结果:
a,b
97,98
2.5 运算符和赋值表达式
2.5.1 赋值运算符和赋值表达式
赋值运算符有“=”、“+=”、“-=”、“*=”、“/=”和“%=”等
用赋值运算符将运算对象连接而成的表达式称为赋值表达式
1.简单赋值运算符
将“=”右边表达式的值赋给左边的变量
例如: a=8;
、 s=a*2+b;
先计算出右边表达式的值,再赋给左边的变量。如果“=”左右两边类型不同,系统会按照赋值类型转换的原则将右边的类型转换成左边的类型
2.复合赋值运算符
在简单赋值运算符前面加上算术运算符就构成复合算术赋值运算符,如下表所示
运算符 | 应用举例 | 等价形式 |
---|---|---|
+= | a+=x | a=a+(x) |
-= | a-=x | a=a-(x) |
*= | a*=x | a=a*(x) |
/= | a/=x | a=a/(x) |
%= | a%=x | a=a%(x) |
3.赋值表达式
由赋值运算符将一个变量和一个表达式连接起来的式子所组成。一般形式为:变量 = 表达式
下面是赋值表达式的例子:
v=4.0*PI*r*r*r/3.0
a=15+(i=6)
b=(x=3)+(y=4)
而 3=x
和 a+b=4
都是错误的赋值表达式
赋值表达式的执行过程是:
- 计算赋值运算符右侧表达式的值;
- 将所计算出的值赋给赋值运算符左侧的变量
注:
赋值运算符的左边只能是变量,不能是常量或表达式
赋值表达式的值就是赋值运算符左边变量的值
赋值表达式的右边也可以是一个赋值表达式
2.5.2算数运算符和算术表达式
1.基本的算术运算符
运算符 | + | - | * | / | % |
---|---|---|---|---|---|
名称 | 加 | 减 | 乘 | 除 | 取余 |
注:
两个整型数据做除法运算时,结果一定是整数
求余运算的结果是两个整型数据相除的余数。求余运算只能用于整型数据的运算
算数运算符两边的数据类型应相同,若不同时,编译系统会先转换为同一数据类型,然后再进行运算
2.单目运算符
-
负号:负数++
自增运算符:使变量的值自加1--
自减运算符:使变量的值自减1
有两种使用形式:
- 前缀方式:用于变量前面,它是 “先计算,后使用”
- 后缀方式:用于变量后面,它是 “先使用,后计算”
3.算术运算符的优先级和结合性
- 单目运算符的优先级高于双目运算符
- 双目算术运算符中*、/、%的优先级高于+、-
- 在优先级相同的情况下,按规定的“结合方向”进行处理
4.算术表达式
- 算术表达式是由算术运算符、运算对象和括号连接起来的式子
- 所有的数学表达式均可写成C语言的算术表达式,但是有些数学表达式无法直接用C语言的算术表达式写出,此时需要调用C语言中的数学函数来实现
注:
表达式中的乘号不能省略,且表达式中的所有字符均应写在同一行上
在表达式中还可以使用多层圆括号(不能使用中括号[]和花括号{}),但是要注意括号的配对
在数学中,5×6÷4的运算结果与6÷4×5的结果相同,都是 7.5,但是C语言中表达式56/4的结果却与6/45的结果不一样
还需注意 8/(8/10)之类的表达式,因为(8/10)的结果为 0,用0做除数将会出现运算溢出的错误,为了不使 8/10 的结果为 0,应将整型常量改为实型常量8.0/10
例:输入一个三位正整数,输出其反序数
#include<stdio.h>
int main()
{
int number = 456;
int a = number / 100; /* 计算百位数 */
int b = (number - a * 100) / 10; /* 计算十位数 */
int c = number % 10; /* 计算个位数 */
printf("反序数是:%d%d%d\n", c, b, a); /* 输出*/
return 0;
}
运行结果:反序数是:321
4. 求字节数运算符
sizeof(…):是一个单目运算符,用于计算数据类型所占的字节数,其一般格式为:
- sizeof(表达式)或sizeof 表达式
- sizeof(数据类型名)
-
#include<stdio.h> int main() { printf("char类型占%d字节\n",sizeof(char)); printf("short int类型占%d字节\n",sizeof(short int)); printf("int类型占%d字节\n",sizeof(int)); printf("float类型占%d字节\n",sizeof(float)); printf("double类型占%d字节\n",sizeof(double)); return 0; }
运行结果:
- char类型占1字节
- short int类型占2字节
- int类型占4字节
- float类型占4字节
- double类型占8字节
1.程序是为实现特定目标或解决特定问题而用计算机语言﹙程序语言
2.6 数据类型转换
2.6.1 自动类型转换
自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换
这种转换不需要程序员干预,会由C语言编译系统自动完成
转换规则是:
把占用内存空间少的(低级)类型向占用空间多的(高级)类型转换,以保证运算的精度
- 图中的纵向箭头表示必定的转换
- 图中的横向箭头表示当经过纵向的转换后,进行运算的数据类型仍然不同时进行的转换方式
自动
#include<stdio.h> int main() { float PI = 3.14159; int s1, r = 5; double s2; s1 = r * r * PI; s2 = r * r * PI; printf("s1=%d, s2=%f\n", s1, s2); return 0; }
类型转换示例
运行结果:s1=78, s2=78.539749
分析:
- 在计算表达式rrPI时,r 和 PI 都被转换成 double 类型,表达式的结果也是 double 类型
- 但由于 s1 为整型,所以赋值运算的结果仍为整型,舍去了小数部分,导致数据失真
2.6.2 强制类型转换
采用强制类型转换运算符将某种数据类型强制转换成指定的数据类型
其一般形式为:(类型说明符)(表达式)
例:强制类型转换示例
#include<stdio.h> int main() { int a=3,b=4; float c; c=(float)(a+b)/2; printf("c=%f\n",c); return 0; }
运行结果:c=3.500000
注:
需强制类型转换中的表达式一定要括起来,否则只对紧随括号后的量进行类型转换
强制类型转换是一种不安全的转换,如果是从高级类型转换成低级类型,则会损失数据的精度
2.6.3 类型转换只是临时性的
目录
无论是自动类型转换还是强制类型转换,都只是为了本次运算而进行的临时性转换
转换的结果也会保存到临时的内存空间,不会改变数据本来的类型或者值
例
#include <stdio.h>
int main(){
double total = 400.8; /* 总价 */
int count = 5; /* 数目 */
double unit; /* 单价 */
int total_int = (int)total;
unit = total / count;
printf("total=%lf, total_int=%d, unit=%lf\n", total, total_int, unit);
return 0;
运行结果:
total=400.800000, total_int=400, unit=80.160000
分析:
- 第 6 行代码,total 变量被转换成了 int 类型才赋值给 total_int 变量
- 而这种转换并未影响 total 变量本身的类型和值
- 如果 total 的值变了,那么 total 的输出结果将变为 400.000000
- 如果 total 的类型变了,那么 unit 的输出结果将变为 80.000000