程序的构成:数据、对数据的处理。
计算机科学家沃思(Nikiklaus Wirth)提出的公式:数据结构 + 算法 = 程序
考虑程序设计方法和使用的语言及开发环境,表达为:程序 = 算法 + 数据结构 + 程序设计方法 + 语言工具和环境
C语言提供的数据元素的类型:
2.2.1 常量(Constant)与符号常量
常量: 在程序运行过程中,其值不能被改变的量。
符号常量:代表常量的标识符(符号)。
[例2.1]
| #define PRICE 30 | |
| main() | |
| { | |
| int num, total; | |
| num = 10; | |
| total = num * PRICE; | |
| printf("total = %d", total); | |
| } | |
2.2.2 变量(Variable)
变量:在程序运行过程中,其值可以被改变的量。
在源程序中,变量用标识符(以字母、数字、下划线组成,且第一个字符必须为字母或下划线)表示。
变量在内存中占据一定的存储单元。变量名的类型表明存储单元的数量(例如,整型变量int,占2字节存储单元。单精度实数float占4字节);变量名表示存储单元的值(该值在程序运行过程中可能随时变化)。可以用运算符&取得存储单元的地址。
合法变量名:
sum, average,class, day, month, student_name, _above, lotus_1_2_3, basic
不合法的变量名: M.D.Jhon, $123, #33, 3D64, a>b
变量名的长度:C语言中未统一规定,随不同开发系统而变。
| 变量名 | 允许长度8 | 允许长度32 |
| student_name | 相同变量名 | 不同变量名 |
| student_number |
Turbo C 2.0缺省允许的变量名长度为32。(Options|Compiler|Source|Identifier length)。

程序设计中变量的命名:
必须满足C语言的语法规定。(以字母、下划线开始,由....构成)。
应该“见名知意”。
C语言对变量的要求:“先定义、后使用”,因为:
1、编译程序不能翻译未定义变量。
2、编译程序在编译时根据变量类型确定存储单元的数量。
3、编译程序在编译时根据变量类型进行语法检查。例,整型变量a、b可以进行“求余”运算 a % b
若把a、b定义为实数,则上述运算非法。
2.3.1 整型常量
C语言中数值常量的表达方式:
| 表达方式 | 意义 | 十进制值 |
| 123 | 十进制 | 123 |
| 0123(数字字符0开头) | 八进制 | 83 |
| 0x123(0x开头) | 十六进制 | 291 |
2.3.2 整型变量
| 有符号 | 无符号 | |
| 基本型(简称整型) | int | unsigned int |
| 短整型 | short或short int | unsigned short |
| 长整型 | long或long int | unsigned long |
C语言标准没有规定整型变量在计算机内存中所占的字节数,它与具体的机器和操作系统有关:
| IBM PC | 所占位数 | 数的范围 |
| int | 16 | -32768~+32767 |
| short | 16 | -32768~+32767 |
| long | 32 | -2147483648~+2147483647 |
| unsigned int | 16 | 0~65535 |
| unsigned short | 16 | 0~65535 |
| unsigned long | 32 | 0~4294967295 |
二、整型变量的定义
int a,b; /* 指定变量a、b为整型 */
unsigned short c, d; /*指定变量c、d为无符号短整型 */
long e,f; /* 指定变量e、f为长整型*/
程序中在函数的开头部分定义变量。
[例2.2]
main() { int a,b,c,d; /* 指定变量a、b、c、d为整型 */
unsigned u; /* 指定变量u为无符号整型 */ a = 12; b = -24; u = 10; c = a + u; d = b+u; printf("a+u = %d, b+u = %d\n", c,d); } 程序运行显示:a+u = 22, b+u = -14
三、整型常量的类型
1、整型常量的值在-32768~+32767范围内,编译器认为是int类型。
2、整型常量的值超过上述范围,而在--2147483648~+2147483647范围内,编译器认为是long类型。
3、在整型常量的值后面加字母L(大写L或小写l),则告诉编译器,把该整型常量作为long类型处理。例:123L、0L。
4、常量无unsigned 型。
2.4.1 实型常量
实数(real)又称为浮点数(float),有两种表达方式:
0.123、 .123、 123.0、
123.、 0.0(必须有小数点)
123e3或123E3、123E-2
2.4.2 实型变量
| 占内存单元 | ||
| 单精度实型变量 | float | 4字节(32位) |
| 双精度实型变量 | double | 8字节(64位) |
例:
float x,y; /* 指定x、y为单精度实型变量 */
double z; /* 指定z为双精度实型变量 */
实型常量不分float和double。
2.5.1 字符常量
用单引号(撇号)括起来的一个字符。如:'a'、'x'、'D'、'?'、'$'。注意,'a'和'A'是不同的字符常量。
以"\"开头的字符序列,称为“转义序列”,“\”使其后面的字符变为另外的意义。见下表。
字符形式 功能 \n 换行符 \t 横向跳格:跳到下一个输出区(每一输出区为8个字符位置) \v 竖向跳格 \b 退格 \r 回车(回到本行起始字符位置) \f 走纸换页 \\ 反斜杠字符\ \' 单引号(撇号)' \ddd 1~3位八进制数所代表的字符。如\101表示'A' \xhh 1~2位十六进制数所代表的字符。如\x40表示'A' 转义序列主要用来控制打印机和屏幕输出。 例:printf("\n sum is %d\n\n",sum);
2.5.2 字符变量
char c1,c2; /* 定义c1、c2为字符变量 */
c1 = 'a'; c2 = 'b';
字符变量在内存中占一字节。
2.5.3 字符数据在内存中的存储形式及其使用方法
字符在内存中以ASCII码存放。
字符 ASCII 'A' 0x40(64) 'B' 0x41(65) 'a' 0x61(97) 'a' 0x62(98) '0' 0x30(48) '1' 0x31(49)
[例2.4]
main() { char c1,c2; c1 = 97; c2 = 98; printf("%c %c",c1,c2); } 该例的输出是:a b
字符以ASCII码存储,其存储方式与整数类似。从而,C语言允许字符和整数之间进行运算。
[例2.5]
| main() | |
| { | char c1,c2; |
| c1 = 'a'; c2 = 'b'; | |
| c1 = c1 - 32; c2 = c2 - 32; | |
| printf("%c %c",c1,c2); | |
| } | |
另外:Turbo C允许使用unsigned char。
2.5.4 字符串常量
字符常量:单引号括起来的一个字符。
字符串常量:双引号括起来的字符序列(0~N个字符)。如:
"How do you do.", "CHINA", "a", "$123.45"
字符串常量在内存中的存放:每一个字符均以其ASCII码存放,且最后添加一个“空字符”(二进制00000000,记为NULL或\0。字符'0'在内存中存0x30即00100000)。例:
字符串常量"CHINA"存放在内存中的情况是:(6字节存储器,不是5字节)
C H I N A \0
因此,字符'a'和字符串"a"的区别是:
字符'a' :1字节(值为97)
字符串"a":2字节(值为97,0)
另外:
char c; c = 'a'; /* 字符'a' */ c = "a"; /* 字符串"a" */
在定义变量的同时指定其初值。例、
int a = 3;
float f = 3.56;
char c = 'a';
int a,b, c = 5; /* 指定c的初值为5,未指定ab的初值 */
注意:多个变量指定相同的初值。
int a = b = c = 3;
int a = 3, b = 3, c = 3;
指定初值是在程序运行时完成的(不是在编译时完成)。
| 定义方法 | 相当的语句 |
| int a = 3; |
int a; |
| int a,b,c=5; |
int a,b,c; |
整型、实型(包括单、双精度)、字符型数据可以混合运算。例、
10 + 'a' + 1.5 - 8765.1234 * 'b'
混合运算时,先转换成同一种类型,然后进行运算。转换规则如下:
例:int数据可以转换为unsigned数据;
float数据可以转换为double数据;
int数据可以转换为double数据,(直接转换,不需先转换为unsigned,long,再转换为double)。
例:
| int i; |
| float f; |
| double d; |
| long e; |
|
上式的运算次序是:
① 进行10+'a'运算。先将'a'转换为整数97,运算结果为整数107。
② 进行i*f运算。先将i和f均转换为double类型(实运算过程总是使用double类型,仅在把结果存入存储器时,才可能使用float类型),运算结果是double类型。
③ 整数107与i*f的积相加。先将整数107转换为double类型(107.0),运算结果是double类型。
④ 进行d/e运算。先将long e转换为double类型,运算结果是double类型。
⑤ 进行③-④运算,结果为double类型。
注意:上述转换过程是由系统自动完成的。(程序员可以强制进行某种转换,见§2.8)。
2.8.1 C运算符简介
算术运算符 +、-、*、/、% 关系运算符 >、<、==、>=、<=、!= 逻辑运算符 !、&&、|| 位运算符 <<、>>、~、|、∧、& 赋值运算符 = 条件运算符 ?、: 逗号运算符 , 指针运算符 *、& 求字节数运算符 sizeof 强制类型转换运算符 (类型) 分量运算符 .(点)、→ 下标运算符 [] 其他 函数调用运算符()
2.8.2 算术运算符和算术表达式
一、基本的算术运算符
| + | 加法运算符,如3+5 |
| 正值运算符,如+3 | |
| - | 减法运算符,如5-2 |
| 负值运算符,如-3 | |
|
* |
乘法运算符,如3*5 |
| / | 除法运算符,如5/3 |
| % | 模运算符(或称求余运算符),如7%4 |
注:-5/3 = -1(余-2) 或 -2(余+1),Turbo C 取-1结果(“向零取整”)。
二、算术表达式和运算符的优先级与结合性
算术表达式:用算术运算符和括号将运算对象(也称操作数,如常量、变量、函数等)连接起来、符合C语法规则的式子。如:
a*b/c - 1.5 + 'a'
运算符的优先级:先乘除、后加减;先括号。
运算符的结合性:运算对象两侧的运算符优先级相同时,运算符的结合方向(左、右)。
左结合性:结合方向为从左至右(先左后右,简称左结合)。算术运算符为左结合。
例:a - b + c
由于算术运算符为左结合,故先执行a-b,再执行加c的运算。
右结合性:结合方向为从右至左(先右后左,简称右结合)。赋值运算符=为右结合。
例: a = b + c
由于赋值运算符=为右结合,先执行右边的b+c,再赋值给a。
运算符两侧的数据类型不同时,先自动进行类型转换,再运算。程序员可以强制进行某种转换。强制类型转换的一般形式是:
(类型名)(表达式)
例、
(double)a; /* 将a转换为double类型 */
(int)(x+y); /* 将x+y的值转换为int类型 */
(float)(5 % 3);/* 将5%3的值转换为float类型 */
区别:
(int)(x+y); /* 将x+y的值转换为int类型 */
(int)x+y; /* 将x的值转换为int类型,再与y相加 */
(int)(x);
(int)x;(表达式仅为一个变量时,括号可以省略)
int(x);
说明:强制类型转换时,得到一个所需类型的中间变量,原来变量的类型不发生变化。
例、 (int)x
变量x的类型不发生变化。
四、自增、自减运算符
自增:使变量的值加1; 自减:使变量的值减1。
|
++i;/* 在使用i之前使i加1 */ --i; /* 在使用i之前使i减1 */ |
|
i++; /* 在使用i之后使i加1 */ i--; /* 在使用i之后使i减1 */ |
例:
|
j = 3; j = ++i; /* 先使i加1,再赋给j。执行后:j=4, i=4 */ |
|
j = 3; j = i++; /* 先把i赋给j,再使i加1。执行后:j=3,i=4 */ |
注意:
(1)++和--只能用于变量,不能用于常量和表达式。例、
5++;
(a+b)++;
#define ONE 1; ONE++;
(2) ++和--的结合方向为“右结合”。例:
|
-i++ 负值运算符-和自增运算符优先级相同 |
(-i)++ |
| -(i++) |
五、有关表达式使用中的问题说明
1. 在表达式中使用++或--,容易出错。
| i = 3; | |
|
k = (i++) + (i++) + (i++) k值等于9。 |
i++:先使用i,再加1。 |
|
k = (++i) + (++i) + (++i) k值等于18。 |
++i:先加1,再使用i。 连续3次使i加1后,i的值等于6 k = 6+6+6 = 18; |
2. 出现多个运算符时,编译器在处理时尽可能多的(从左到右)将若干个字符组合成一个运算符。例、
| i+++j; | (i++)+j |
| i+(++j) |
3. Turbo C中,调用函数时,实际参数的处理顺序是从右到左(称为C调用约定。实际参数的处理顺序从左到右,称为PASCAL调用约定)。例:
|
i = 3; printf("%d,%d",i,i++); |
先右:i++,先使用i(3),再使i加1。 后左:i(现在值为4)。 因此,输出结果:4,3 |
菜单:Options|Compiler|Code generation|Calling convention

一、赋值运算符:=
作用:将一个表达式的值赋给变量。例、
a = 3;/*常数3赋给变量a。常数是特殊的表达式 */
a = b + c + 1;
二、赋值时的类型转换
当赋值运算符两侧的类型不同时,在赋值前进行类型转换。
1、float、double int:舍弃小数(截断)。
2、int float、double:值不变。
3、char(1字节) int(2字节)
(1)(unsigned char) int:赋给int的低8位,int的高8位补0。
(2)(signed char)int:赋给int的低8位,若signed char的最高位是0,则int的高8位全为0;若signed char的最高位是1,则int的高8位全为1。(称为“符号扩展”)
4、 int long int(符号扩展)
long int int(截断)
5、 unsigned int int
6、非unsigned数据 位数相同的unsigned 数据。
三、复合的赋值运算符
| 复合赋值运算符 | 例子语句 | 等价语句 |
| += | a += 3; | a = a + 3; |
| *= | x *= y + 8; | x = x*(y+8) |
| %= | x %= 3; | x = x % 3; |
四、赋值表达式
一般形式:<变量> <赋值运算符> <表达式>
例:
赋值表达式: a = 5
赋值语句: a = 5;
赋值表达式中的“表达式”也可以是赋值表达式。例、
a = (b = 5) /* b的值等于5,表达式b=5的值等于5,因此a的值等于5 */
a = b = 5 /* 与上述表达式的意义相同 */
例、
a = 5 + (c = 6) /* c=6, a=11 */
a = (b = 4) + (c = 6) /* c=6, b=4, a=10 */
a = (b = 10) / (c = 2) /* c=2,b=10,a=5 */
a += a -= a*a /* 先a=a-a**,再a=a+a */
逗号运算符:,
逗号表达式:用逗号运算符把两个表达式连接起来的表达式。其一般形式为:
表达式1,表达式2
例、
3+5,6+8 /* 是一个逗号表达式 */
逗号表达式的值等于“表达式2”的值,但C语言中使用逗号表达式的一般目的是分别获得两个表达式的值,因此,逗号运算符又称为“顺序求值运算符”。
逗号表达式可以扩展为更一般的形式:
表达式1,表达式2,表达式3,.....,表达式n
例、
a = 3*5,a*4
(a=3*5,a*4),a+5
区别:(逗号运算符在所有运算符中优先级最低)
x = (a=3,6*3) /*赋值表达式 */
x = a =3,6*a /* 逗号表达式 */
区别:(逗号可以作运算符,也可以作分隔符)
printf("%d,%d,%d",a,b,c); /* 逗号做分隔符 */
printf("%d,%d,%d",(a,b,c),b,c); /* (a,b,c)中的逗号是运算符,其余逗号是分隔符 */
本章有关常量、变量、运算符、表达式的细节非常多,它们不是程序设计的最重要的内容,但细节错误也导致程序最终错误,因此,还是要引起注意。
细节不能死记,要注意本质概念;对于无把握的细节,要在Turbo C中进行测试。