C程序设计(第三版)
第 3章 数据类型、运算符与表达式
C 语言程序设计
2009-7-31
本章要点
– 数据的描述规则
– 数据的操作规则
2009-7-31
本章主要内容
3.1 C的数据类型
3.2 常量与变量
3.3 整型数据
3.4 浮点型数据运行
3.5 字符型数据
3.6变量赋初值
3.7 各类数值型数据间的混合运算
3.8 算术运算符和算术表达式
3.9 赋值运算符和赋值表达式
3.10 逗号运算符和逗号表达式
2009-7-31
补充:计算机中的内存
回忆数据处理的过程
内存(主存)
– RAM,随机存储器(在程序运行过程中,
构成程序的指令和数据存储在此)
– ROM:只读存储器(制造机器时放置的信息,主要是控制各种设备的,如显示器,硬盘驱动器,键盘等,在 PC中,
这些程序叫做 BIOS)
2009-7-31
内存的容量
可以把计算机的 RAM想象成一组排列好的箱子。
每个箱子有两种状态,满的( 1),空的( 0)。
每个箱子叫做一个位( bit),即二进制数位
( binary bit)的缩写。
为了方便使用,这些位按 8个分成一组,称为一个字节 B( Byte)。
为了便于引用特定字节的内容,每个字节由一个数字标记,第一个字节从 0开始,这种标记叫做地址。
1GB=1024MB=220KB=230B
2009-7-31
补充:计算机中正,负数的表示例如,109 = (1101101)2
要区别:+ 109 和 - 109
方法是,将符号也数码化即,正的符号 + 用 0 表示负的符号 - 用 1 表示
∴ 计算机中的数表示方法是:
符号位 + 二进制数值 (以 8bit 为例 )
+ 109 → + 110 1101 → 0110 1101
- 109 → - 110 1101 → 1110 1101
2009-7-31
问题:计算机计算复杂化例如计算,( -19) +( +22)
1001 0011 + 0001 0110
解决的方法是:
使用 反码 或 补码 的表示方法(按前述表示的编码称为 原码 ),即能将减法一律转换为加法。
需要判断符号是否相同:
如果相同,结果符号不变,并进行绝对值相加
如果不同,结果取绝对值大的数的符号,并进行绝对值相减
2009-7-31
原码、反码和补码
正数,原码、反码、补码相同
– 符号位为 0,数值为对应的二进制数。
+ 109
[01101101]原 = [01101101]反 = [01101101]补
负数,
– 原码 符号位为 1,数值为绝对值的二进制数。 - 109 [11101101]原
– 反码 符号位为 1,数值为绝对值的二进制数各位变反。 - 109 [10010010]反
– 补码 符号位为 1,数值为绝对值的二进制数各位变反加 1。 - 109 [10010011]补
2009-7-31
3.1 C的数据类型
C语言提供了以下一些数据类型。
数据类型 构造类型指针类型空类型( 无值类型) void
枚举类型 enum
数组类型结构类型 struct
联合类型 union
基本类型整型 int
字符型 char
实型(浮点型)
单精度实型
float
双精度实型
double
2009-7-31
3.2 常量与变量
3.2.1 常量和符号常量
在程序运行过程中,其值不能被改变的量称为常量
常量区分为不同的类型:
整型 100,125,-100,0
实型 3.14,0.125,-3.789
字符型 ‘ a’,‘b’,‘ 2’
字符串 ‘ a’,‘ab’,‘ 1232’
2009-7-31
例 3.1 符号常量的使用
#define PRICE 30
#include <stdio.h>
void main ( )
{
int num,total;
num=10;
total=num * PRICE;
printf(″total=%d\n″,total);
}
符号常量,用一个标识符代表一个常量。符号常量的值在其作用域内不能改变,也不能再被赋值。
运行结果,total=300
说明,程序中用 #define命令行定义 PRICE代表常量 30,此后凡在本文件中出现的 PRICE都代表 30,
可以和常量一样进行运算说明,如再用赋值语句给 PRICE赋值是错的
PRICE=40; /* 错误,不能给符号常量赋值
2009-7-31
3.2 常量与变量
3.2.2 变量
变量代表内存中具有特定属性的一个存储单元,它用来存放数据,这就是变量的值,在程序运行期间,这些值是可以改变的。
变量名实际上是一个以一个名字对应代表一个地址,在对程序编译连接时由编译系统给每一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。
2009-7-31
eg,#include <stdio.h>
void main()
{
int salary;
salary=10000;
printf(“My salary is %d”,salary);
}
在程序中可以有任意多个变量。
变量的值并不固定,根据程序中的指令可以被多次改变。
2009-7-31
3.2 常量与变量变量命名的规定,C语言规定标识符只能由字母、
数字和下划线三种字符组成,且第一个字符必须为字母或下划线。
例,sum,_total,month,Student_name,
lotus_1_2_3,BASIC,li_ling
M.D.John,¥ 123,3D64,a>b
2009-7-31
3.2 常量与变量注意:
编译系统将大写字母和小写字母认为是两个不同的字符。
变量名中可以使用的字符个数由编译器决定,通常最多支持 31个字符,变量名太长会使代码更难理解。
建议变量名的长度最好不要超过 8个字符。
在选择变量名和其它标识符时,应注意做到?见名知意?,即选有含意的英文单词 (或其缩写)
作标识符。
要求对所有用到的变量作强制定义,也就是? 先定义,后使用? 。
2009-7-31
3.3 整型数据
3.3.1整型常量的表示方法整型常量即整常数。在C语言中,整常数可用以下三种形式表示:
(1)十进制整数。
如,123,-456。
(2)八进制整数。以 0头的数是八进制数。
如,0123表示八进制数 123,等于十进制数 83,-011表示八进制数 -11,即十进制数 -9。
(3)十六进制整数。以 0x开头的数是 16进制数。
如,0x123,代表 16进制数 123,等于十进制数 291。 -0x12等于十进制数
- 10。
2009-7-31
整型变量 —存储整数的变量
3.3.2 整型变量
– 整数:没有小数点的数字。
– 1,1099000,2.0?
(1)整型数据在内存中的存放形式数据在内存中是以二进制形式存放的。
如,int i; /* 定义为整型变量 */
i=10; /* 给 i赋以整数 10 */
– eg,more variables
– 一个语句中可以声明多个变量,数据类型之后的变量名由逗号分隔;
– 所有声明语句位于该函数的可执行代码的开头。
2009-7-31
3.3 整型数据
(2)整型变量的分类共六种有符号基本整型有符号短整型有符号长整型无符号基本整型无符号短整型无符号长整型
(signed)int
(signed)short (int )
(signed) long (int)
unsigned int
unsigned short (int)
unsigned long (int)
注意,括号表示其中的内容是可选的,
2009-7-31
3.3 整型数据
整数类型的有关数据( 典型大小 ):
类型 类型说明符 长度 数的范围基本型 int 2字节 -32768~ 32767
短整型 short 2字节 -215~ 215-1
长整型 long 4字节 -231~ 231-1
无符号整型 unsigned 2字节 0~ 65535
无符号短整型 unsigned short 2字节 0~ 65535
无符号长整型 unsigned long 4字节 0~( 232-1)
注意:
十进制数 10的二进制形式为 1010,Turbo C 2.0和 Turbo C++ 3.0为一个整型变量在内存中分配 2个字节的存储单元 (不同的编译系统为整型数据分配的字节数是不相同的,VC++ 6.0则分配 4个字节)。
2009-7-31
3.3 整型数据例如:整数 13在内存中实际存放的情况:
2009-7-31
3.3 整型数据
(3)整型变量的定义,
C规定在程序中所有用到的变量都必须在程序中定义,即? 强制类型定义? 。
例如,
int a,b(指定变量a、b为整型)
unsigned short c,d;(指定变量c、d为无符号短整型)
long e,f;(指定变量e、f为长整型)
int a=0; (在声明变量时,初始化变量通常是种好方法)
2009-7-31
例 3.2 整型变量的定义与使用
#include <stdio.h>
void main()
{ int a,b,c,d; /* 指定a、b、c、d为整型变量
*/
unsigned 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
2009-7-31
例 3.3 整型数据的溢出
#include <stdio.h>
void main()
{int a,b;
a=32767;
b=a+1;
printf(“%d,%d \n”,a,b);
} 说明,数值是以补码表示的。一个整型变量只能容纳 -32768~ 32767
范围内的数,无法表示大于 32767或小于 -32768的数。遇此情况就发生?溢出?。
运行结果,32767,-32768
2009-7-31
3.3 整型数据
3.3.3 整型常量的类型
(1)一个整数,如果其值在 -32768~ +32767范围内,认为它是 int型,它可以赋值给 int型和 long int型变量。
(2) 一个整数,如果其值超过了上述范围,而在 -2147483637~
+2147483647范围内,则认为它是为长整型。可以将它赋值给一个 long
int型变量。
(3) 如果所用的 C版本(如 Turbo C)分配给 short int与 int型数据在内存中占据的长度相同,则它的表数范围与 int型相同。因此一个 int型的常量同时也是一个 short int型常量,可以赋给 int型或 short int型变量。
(4) 一个整常量后面加一个字母 u或 U,认为是 unsigned int型,如
12345u,在内存 中按 unsigned int规定的方式存放 (存储单元中最高位不作为符号位,而用来存储数据 )。 如果写成 -12345u,则先将 -12345
转换成其补码 53191,然后按无符号数存储。 (可验证 )
(5) 在一个整常量后面加一个字母 l或 L,则认为是 long int型常量。
例如,123l.432L.0L
2009-7-31
整型变量常用基本运算
算术语句
– Variable_Name=Arithmetic_Expression;
– 算术表达式用算术运算符( +,-,*,/)把存在变量中的值或数字连接在一起,构成了算式。
– =定义的是一种赋值操作。
– 生成数字值的表达式都叫算术表达式。
– eg,3,1+2,a+b
– 基础算术运算符:
运算符 操作
+ 加法
_ 减法
* 乘法
/ 除法
% 取余
2009-7-31
程序举例
减法和乘法
– 已知总共的小甜饼数和每个小甜饼所含卡路里数,根据吃掉的小甜饼数来计算剩余小甜饼数及总共摄取的热量。
第一次吃掉 2个小甜饼后计算剩余数量;
第二次吃掉 3个小甜饼后计算剩余数量,并计算两次共摄入的热量是多少。
– 分析:需要声明或要使用的变量有哪些?
– 对变量进行命名和确定所用数据类型。
– 写程序实现。
2009-7-31
试试看:除法和取模运算
假设一罐小甜饼有 45块,一组孩子有 7个。
你要给孩子平分小甜饼,需要计算出给每个孩子几块小甜饼,然后计算出余下多少小甜饼。
写程序实现 。
2009-7-31
有关整数除法
在除法中,如果一个运算数具有负号,结果将是负数。
– -45/7 == 45/-7
如果两个运算数的符号相同,那么结果是正数。
– -45/-7 == 45/7
对于取模运算,结果的符号与左边运算数的符号一致。
– 45%-7 != -45%7,-45%-7?
2009-7-31
3.4 浮点型数据
3.4.1浮点型常量的表示方法两种表示形式小数指数
0.123
3e-3
注意,字母 e(或 E)之前必须有数字,且 e后面的指数必须为整数
1e3,1.8e-3,-123e-6,-1e-3
e3,2.1e3.5,.e3,e
2009-7-31
3.4 浮点型数据规范化的指数形式:
在字母 e(或 E)之前的小数部分中,小数点左边应有一位(且只能有一位)非零的数字,
例如,123.456可以表示为:
123.456e0,12.3456e1,1.23456e2,0.123456e3,
0.0123456e4,0.00123456e
其中的 1.23456e2称为? 规范化的指数形式? 。
2009-7-31
3.4 浮点型数据
3.4.2 浮点型变量
(1)浮点型数据在内存中的存放形式一个浮点型数据一般在内存中占 4个字节 (32位 )。与整型数据的存储方式不同,浮点型数据是按照指数形式存储的。
系统把一个浮点型数据分成小数部分和指数部分,分别存放。
下图为十进制示意图。
2009-7-31
类型 位数 数的范围 有效数字
float 32 10-37 ~ 1038 6~7 位
double型 64 10-307~10308 15~16位
long double 128 10-4931~104932 18~19位
3.4 浮点型数据
(2) 浮点型变量的分类浮点型变量分为单精度( float型)、双精度( double型)和长双精度型
( long double)三类形式。
2009-7-31
例 3.4 浮点型数据的 舍入误差
#include <stdio.h>
void main()
{float a,b;
a = 123456.789e5;
b = a + 20 ;
printf(“%f \n”,b);
}说明,一个浮点型变量只能保证的有效数字是 7位有效数字,后面的数字是无意义的,并不准确地表示该数。应当避免将一个很大的数和一个很小的数直接相加或相减,否则就会?丢失?小的数运行结果,12345678848.000000
2009-7-31
3.4 浮点型数据
3.4.3 浮点型常量的类型
C编译系统将浮点型常量作为双精度来处理。
例如,f = 2.45678 * 4523.65
f = 2.45678f*4523.65f
系统先把 2.45678和 4523.65作为双精度数,然后进行相乘的运算,得到的乘也是一个双精度数。最后取其前 7位赋给浮点型变量 f。如是在数的后面加字母 f或 F(如 1.65f,654.87F),这样编译系统就会把它们按单精度( 32位)处理。
2009-7-31
作业:
1 编写一个程序,提示用户以英寸为单位输入一个距离,然后分别以码、英尺和英寸输出该距离。
2 你在销售一种产品,它有两种版本,第一种是标准版,价格为 3.5美元,另一种是豪华版,价格为 5.5美元,编写一个程序,利用你学过的东西,提示用户输入产品类型和数量,然后计算并输出对应这种数量的价格。
提示,scanf()的使用,参考 P5 例 1.3
2009-7-31
3.5 字符型数据
3.5.1 字符常量
(1)用单引号包含的一个字符是字符型常量
(2)只能包含一个字符
a?,?A?,?1?
abc?,,a”?
2009-7-31
3.5 字符型数据有些以? \”开头的特殊字符称为转义字符
\n 换行
\t 横 向跳格
\b 退格,将当前位置移到前一列
\r 回 车
\\ 反 斜杠
\ddd ddd表示 1到 3位八进制数所代表的字符
\xhh hh表示 1到 2位十六进制数所代表的字符
2009-7-31
例 3.5 转义字符的使用
#include <stdio.h>
void main()
{printf( ″ ab c \t
de\rf\tg\n″ ) ;
printf(″h \ti\b\bj k\n″);

打印机上的显示结果:
fab c gde
h jik
显示屏上 的运行结果:
f gde
h j k
2009-7-31
3.5 字符型数据
3.5.2字符变量
字符型变量用来存放字符常量,注意只能放一个字符 。
字符变量的定义形式如下,char c1,c2;
在本函数中可以用下面语句对 c1,c2赋值:
c1= ‘ a?; c2= ‘ b? ;
一个字符变量在内存中占一个字节。
2009-7-31
3.5 字符型数据
3.5.3 字符数据在内存中的存储形式及其使用方法
一个字符常量存放到一个字符变量中,实际上并不是把该字符的 字型 放到内存中去,而是将该字符的相应的
ASCII代码 放到存储单元中。这样使字符型数据和整型数据之间可以通用。
注意,
一个字符数据既可以以字符形式输出,也可以以整数形式输出。
2009-7-31
例 3.6 向字符变量赋以整数。
#include <stdio.h>
void main()
{char c1,c2;
c1=97;
c2=98;
printf(“%c %c \n”,c1,c2);
printf(“%d %d \n”,c1,c2);
}? 说明,在第3和第 4行中,将整数 97和 98分别赋给 c1和 c2,它的作用相当于以下两个赋值语句:
c1= ′ a ′;c2 = ′ b ′;
因为’ a’ 和’ b’ 的 ASCII码为 97和 98
运行结果:
a b
97 98
2009-7-31
例 3.7 大小写字母的转换
#include <stdio.h>
void main()
{char c1,c2;
c1=’a’;
c2=’b’;
c1=c1-32;
c2=c2-32;
printf(,% c % c″,c1,c2);

说明,程序的作用是将两个小写字母 a和 b转换成大写字母 A和 B。从ASCII代码表中可以看到每一个小写字母比它相应的大写字母的
ASCII码大 32。C语言允许字符数据与整数直接进行算术运算。
运行结果,A B
2009-7-31
3.5 字符型数据说明:
有些系统(如 Turbo C)将字符变量定义为 signed
char型。其存储单元中的最高位作为符号位,它的取值范围是 -128~ 127。如果在字符变量中存放一个
ASCII码为 0~ 127间的字符,由于字节中最高位为 0,
因此用 %d输出字符变量时,输出的是一个正整数。如果在字符变量中存放一个 ASCII码为 128~ 255间的字符,由于在字节中最高位为 1,用 %d格式符输出时,
就会得到一个负整数。
2009-7-31
3.5 字符型数据
3.5.4字符串常量
字符串常量是一对双撇号括起来的字符序列,
合法的字符串常量,
How do you do.”,“CHINA”,? a”,
$123.45”
可以输出一个字符串,如
printf(“How do you do.”);
2009-7-31
3.5 字符型数据
a ’ 是字符常量,? a? 是字符串常量,二者不同。
如,假设C被指定为字符变量,char c
c=’a’;
c=” a” ; c=” CHINA”;
结论,不能把一个字符串常量赋给一个字符变量。
2009-7-31
C规定:在每一个字符串常量的结尾加一个? 字符串结束标志?,以便系统据此判断字符串是否结束。
C规定以字符 ’ \0 ’ 作为字符串结束标志。
如,如果有一个字符串常量?CHINA?,实际上在内存中是:
C H I N A \0
它占内存单元不是5个字符,而是6个字符,最后一个字符为’\0’。
但在输出时不输出’\0’。
3.5 字符型数据
2009-7-31
补充(找边界)
系统或编译器不同,数字类型值的范围的边界就不同。
如何在程序中确定某个实例的边界?
C语言标准库中的头文件提供了相关的信息。
limits.h:INT_MIN,INT_MAX,CHAR_MIN,
CHAR_MAX等
float.h:FLT_MIN,FLT_MAX,DBL_MIN,D
BL_MAX等
2009-7-31
试试看:找边界
#include <stdio.h>
#include < limits.h > /* For limits on integer types */
#include <float.h> /* For limits on floating-point types */
void main()
{
printf("Variables of type char store values from %d to %d",
CHAR_MIN,CHAR_MAX);
printf("\nVariables of type unsigned char store values from 0 to %u",
UCHAR_MAX);
printf("\nVariables of type short store values from %d to %d",
SHRT_MIN,SHRT_MAX);
printf("\nVariables of type unsigned short store values from 0 to %u",
USHRT_MAX);
printf("\nVariables of type int store values from %d to %d",INT_MIN,INT_MAX);
printf("\nVariables of type unsigned int store values from 0 to %u",UINT_MAX);
printf("\nVariables of type long store values from %d to %d",
LONG_MIN,LONG_MAX);
printf("\nVariables of type unsigned long store values from 0 to %u",
ULONG_MAX);
printf("\n\nThe size of the smallest non-zero value of type float is %.3e",
FLT_MIN);
printf("\nThe size of the largest value of type float is %.3e",FLT_MAX);
printf("\nThe size of the smallest non-zero value of type double is %.3e",
DBL_MIN);
printf("\nThe size of the largest value of type double is %.3e",DBL_MAX);
}
2009-7-31
补充 2:输入输出格式说明符
输入格式说明符输入格式说明符 读入的值
%c 单个字符
%hd short型的值
%d int型的值
%ld long型的值
%f或 %e float型的值
%lf或 %le double型的值
2009-7-31
输出格式说明符
– 输出格式说明符 输出
%[-][width]c 字符值
%[-][width]d 有符号十进制整数
%[width]x 无符号使用,abcdef”的十六进制整数
%[width]X 无符号使用,ABCDEF”的十六进制整数
%[-][width]ld 有符号十进制长整数
%[-][width]u 无符号十进制整数
%[-][width][.precision]f 没有指数的浮点数字
%[-][width][.precision]e 有指数的浮点数字根据变量的类型,选择合适的输出格式说明符,否则回造成结果无法正常显示。
2009-7-31
3.6 变量赋初值
(1)C语言允许在定义变量的同时使变量初始化如,int a=3; // 指定a为整型变量,初值为3
float f=3.56; // 指定f为浮点型变量,初值
//为3,56
char c= ‘a’; // 指定c为字符变量,初值
//为‘ a’
2009-7-31
3.6 变量赋初值
(2)可以使被定义的变量的一部分赋初值。
如,int a,b,c=5; 表示指定a、b、c为整型变量,但只对c初始化,c的初值为5
(3)如果对几个变量赋以同一个初值,
应写成,int a=3,b=3,c=3; 表示a、b、c的初值都是3。
不能写成 ∶ int a=b=c=3;
注意,初始化不是在编译阶段完成的而是在程序 运行时 执行本函数时赋初值的,相当于有一个赋值语句 。
2009-7-31
3.7 各类数值型数据间的混合运算混合运算,整型(包括 int,short,long)、浮点型(包括
float,double)可以混合运算。在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算,
说明:
这种类型转换是由系统自动进行的。
2009-7-31
3.8 术运算符和算术表达式
3.8.1 C运算符简介
C的运算符有以下几类:
(1)算术运算符 ( + - * / %)
(2)关系运算符 (><==>=<=!=)
(3)逻辑运算符 (!&& ||)
(4)位运算符 ( << >> ~ |∧ &)
(5)赋值运算符 (=及其扩展赋值运算符)
(6)条件运算符 (?:)
(7)逗号运算符 (,)
(8)指针运算符 ( *和&)
(9)求字节数运算符(sizeof)
(10)强制类型转换运算符( (类型) )
(11)分量运算符(,->)
(12)下标运算符([ ])
(13)其他 (如函数调用运算符())
2009-7-31
3.8 算术运算符和算术表达式
3.8.2 算术运算符和算术表达式
(1)基本的算术运算符,
+ (加法运算符,或正值运算符。如,3+5、+3)
- (减法运算符,或负值运算符。如,5-2、-3)
* (乘法运算符。如,3 *5)
/ (除法运算符。如,5/3)
% (模运算符,或称求余运算符,%两侧均应为整型数据,如,7%4的值为3)。
2009-7-31
3.8 算术运算符和算术表达式
(2) 算术表达式和运算符的优先级与结合性,
用算术运算符和括号将运算对象 (也称操作数)连接起来的、符合C语法规则的式子,称为C算术表达式 。运算对象包括常量、变量、函数等。
例如,a *b/c-1,5+ ′a′
是一个合法的表达式
2009-7-31
C语言规定了运算符的优先级和结合性。
在表达式求值时,先按运算符的优先级别高低次序执行,例如先乘除后加减。
C规定了各种运算符的结合方向 (结合性 )
算术运算符的结合方向为? 自左至右?,即先左后右 。
3.8 算术运算符和算术表达式
2009-7-31
3.8 算术运算符和算术表达式
(3)强制类型转换运算符可以利用强制类型转换运算符将一个表达式转换成所需类型。
一般形式,(类型名)(表达式)
例如:
(double)a 将a转换成 double类型
(int)(x+y) 将 x+y的值转换成整型
(float)( 5%3) 将 5%3的值转换成 float型
2009-7-31
例 3.8 强制类型转换。
#include <stdio.h>
voidmain()
{float x;
int i;
x=3.6;
i=(int)x;
printf("x=%f,i=%d\n",x,i);

说明,有两种类型转换,一种是在运算时不必用户指定,系统自动进行的类型转换,如 3+6.5。第二种是强制类型转换。当自动类型转换不能实现目的时,可以用强制类型转换。
运行结果:
x= 3.600000,i=3
2009-7-31
3.8 算术运算符和算术表达式
(4) 自增、自减运算符作用是使变量的值增1或减1
如,
++i,--i(在使用i之前,先使i的值加
(减)1)
i++,i--(在使用i之后,使i的值加(
减)1)
2009-7-31
3.8 算术运算符和算术表达式
i++与 ++i的区别:
++i是先执行i=i+1后,再使用i的值;
i++是先使用i的值后,再执行i=i+1。
例如:
①j=++i;
i的值先变成 4,再赋给j,j的值均为4
②j=i++;
先将 i的值 3赋给j,j的值为3,然后i变为4
2009-7-31
3.8 算术运算符和算术表达式注意:
(1)自增运算符(++),自减运算符(--),只能用于变量,而不能用于常量或表达式,
(2)++和--的结合方向是? 自右至左? 。
自增(减)运算符常用于循环语句中使循环变量自动加1。也用于指针变量,使指针指向下一个地址
2009-7-31
3.8 算术运算符和算术表达式
(5) 有关表达式使用中的问题说明
① ANSI C并没有具体规定表达式中的子表达式的求值顺序,
允许各编译系统自己安排。
例如,对表达式 a = f1( )+f2( )
并不是所有的编译系统都先调用 f1( ),然后调用 f2( )。在有的情况下结果可能不同。有时会出现一些令人容易搞混的问题,因此务必要小心谨慎 。
2009-7-31
3.8 算术运算符和算术表达式
② C语言中有的运算符为一个字符,有的运算符由两个字符组成,为避免误解,最好采取大家都能理解的写法。
例如,不要写成 i+++j的形式,而应写成
(i++)+j的形式 或 i+( ++j)的形式
2009-7-31
3.8 算术运算符和算术表达式
③ 在调用函数时,实参数的求值顺序,C标准并无统一规定。
例如,i的初值为3,如果有下面的函数调用:
printf( ″%d,%d ″,i,i++) 在有的系统中,从左至右求值,输出?3,3?。在多数系统中对函数参数的求值顺序是自右而左,printf函数输出的是?4,
3?。 以上这种写法不宜提倡,最好改写成
j = i++;
printf("%d,%d",j,i)
不要写出别人看不懂的也不知道系统会怎样执行程序
2009-7-31
3.9 赋值运算符和赋值表达式
(1)赋值运算符赋值符号?=?就是赋值运算符,它的作用是将一个数据赋给一个变量。如?a=3?的作用是执行一次赋值操作(或称赋值运算)。把常量3赋给变量a。也可以将一个表达式的值赋给一个变量,
2009-7-31
3.9 赋值运算符和赋值表达式
(2)类型转换如果赋值运算符两侧的类型不一致,但都是数值型或字符型时,在赋值时要进行类型转换 。
① 将浮点型数据 ( 包括单,双精度 ) 赋给整型变量时,舍弃浮点数的小数部分 。
如,i为整型变量,执行? i=3.56” 的结果是使
i的值为3,以整数形式存储在整型变量中,
2009-7-31
3.9 赋值运算符和赋值表达式
② 将整型数据赋给单、双精度变量时,数值不变,
但以浮点数形式存储到变量中如,将 23赋给 float变量f,即执行f= 23,先将 23转换成 23,00000,再存储在f中。
将 23赋给 double型变量d,即执行d= 23,系统将 23补足有效位数字为 23,00000000000000,然后以双精度浮点数形式存储到变量d中。
2009-7-31
3.9 赋值运算符和赋值表达式
③ 将一个 double型数据赋给 float变量时,截取其前面 7位有效数字,存放到 float变量的存储单元( 4个字节)中。但应注意数值范围不能溢出。
如,float f;double d=123.456789e100; f=d;
就出现溢出的错误。
如果将一个 float型数据赋给 double变量时,数值不变,有效位数 扩展到 16位,在内存中以 8个字节存储
2009-7-31
3.9 赋值运算符和赋值表达式
④ 字符型数据赋给整型变量时,由于字符只占 1个字节,而整型变量为2个字节,因此将字符数据(8个二进位)放到整型变量存储单元的低8位中。
2009-7-31
第一种情况,低位对应、高位补零若所用系统将字符处理为无符号字符类型,或程序已将字符变量定义为 unsigned char型,则将字符的8位放到整型变量低8位,高
8位补零。 例如:
将字符‘\ 376?赋给 int型变量i
第二种情况,符号扩展若所用系统(如 Turbo C++)将字符处理为带符号( signed
char)时,若字符最高位为0,则整型变量高8位补0;若字符最高位为1,则高8位全补1。这称为? 符号扩展?,这样做的目的是使数值保持不变,如变量c(字符 ‘ \ 376’)以整数形式输出为-2,i的值也是-2。
2009-7-31
3.9 赋值运算符和赋值表达式
⑤ 将一个 int,short,long型数据赋给一个 char型变量时,只将其低 8位原封不动地送到 char型变量(即截断)。 例如,int i=289;char c=′a′;c=i;
c的值为 33,
如果用? %c” 输出 c,将得到字符? !”
!的 ASCII码为 33。
赋值情况,
2009-7-31
3.9 赋值运算符和赋值表达式
⑥ 将带符号的整型数据( int型)赋给 long型变量时,要进行符号扩展,将整型数的 16位送到 long型低 16位中,
如果 int型数据为正值(符号位为0),则 long型变量的高 16位补0;
如果 int型变量为负值(符号位为1),则 long型变量的高 16位补1,以保持数值不改变。
反之,若将一个 long型数据赋给一个 int型变量,只将
long型数据中低 16位原封不动地送到整型变量(即截断)。
2009-7-31
3.9 赋值运算符和赋值表达式例如,int a; long b=8; a=b
赋值情况如下,
如果b= 65536(八进制数
0200000),
则赋值后a值为0。
2009-7-31
3.9 赋值运算符和赋值表达式
⑦ 将 unsigned int型数据赋给 long int型变量时,不存在符号扩展问题,只需将高位补0即可。将一个
unsigned类型数据赋给一个占字节数相同的非
unsigned型整型变量(例如,unsigned int
->int,unsigned long->long,unsigned short
->short),将 unsigned型变量的内容原样送到非
unsigned型变量中,但如果数据范围超过相应整型的范围,则会出现数据错误。
2009-7-31
3.9 赋值运算符和赋值表达式例如,unsigned int a= 65535; int b;b=a;
将a整个送到b中,由于b是 int,第1位是符号位,
因此 b成了负数。根据补码知识可知,b的值为 -1,
可以用 printf( ″%d″,b); 来验证。
⑧ 将 signed型数据赋给长度相同的 unsigned型变量,也是原样照赋(符号位也作为数值一起传送)。
2009-7-31
例 3.9 有符号数据传送给无符号变量。
#include <stdio.h>
void main()
{ unsigned a;
int b=-1;
a=b;
print( ″ %u \n″,a);

说明,? %u” 是输出无符号数时所用的格式符。如果b为正值,且在0~ 32767之间,则赋值后数值不变。
运行结果:
65535
2009-7-31
3.9 赋值运算符和赋值表达式
(3) 复合的赋值运算符在赋值符? =? 之前 加上其他运算符,可以构成复合的运算符 。
例如,
a+=3 等价于 a=a+3
x *=y+8 等价于 x=x *(y+8)
x%=3 等价于 x=x%3
2009-7-31
3.9 赋值运算符和赋值表达式为便于记忆,可以这样理解:
① a += b (其中 a为变量,b为表达式 )
② a += b(将有下划线的? a+”移到? =”右侧)
|___↑
③ a = a + b (在? =”左侧补上变量名 a)
2009-7-31
3.9 赋值运算符和赋值表达式注意,如果b是包含若干项的表达式,则相当于它有括号。
如,① x %= y+3
② x %= (y+3)
|__↑
③ x = x %(y+3)(不要错写成 x=x%y+3)
C语言规定可以使用10种复合赋值运算符:
+=,-=,*=,/=,%=,<<=,>>=,&=,∧ =,|

2009-7-31
3.9 赋值运算符和赋值表达式
(4) 赋值表达式由赋值运算符将一个变量和一个表达式连接起来的式子称为? 赋值表达式? 。
一般形式为,
<变量 ><赋值运算符 ><表达式 >
例如,,a= 5”是一个赋值表达式
2009-7-31
3.9 赋值运算符和赋值表达式对赋值表达式求解的过程是:
①求赋值运算符右侧的? 表达式? 的值 ;
② 赋给赋值运算符左侧的变量。
例如,赋值表达式? a =3*5”的值为 15,执行表达式后,变量 a
的值也是 15。
注意,一个表达式应该有一个值
2009-7-31
3.9 赋值运算符和赋值表达式左值 (lvalue),赋值运算符左侧的标识符
变量可以作为左值 ;
而表达式就不能作为左值 (如 a+b);
常变量也不能作为左值,
右值 (lvalue),出现在赋值运算符右侧的表达式左值也可以出现在赋值运算符右侧,因而左值都可以作为右值。
2009-7-31
3.9 赋值运算符和赋值表达式赋值表达式中的?表达式?,又可以是一个赋值表达式。 例如,a=(b=5)
分析,括弧内的? b=5”是一个赋值表达式,它的值等于 5。执行表达式? a=(b=5)”相当于执行
b=5”和? a= b”两个赋值表达式。 赋值运算符按照? 自右而左? 的结合顺序,因此,? (b= 5)”
外面的括弧可以不要,即? a=(b=5)”和? a=b=5”
等价。
2009-7-31
3.9 赋值运算符和赋值表达式请分析下面的赋值表达式 ∶ (a=3*5)=4*3
分析,先执行括弧内的运算,将 15赋给 a,然后执行
4*3的运算,得 12,再把 12赋给 a。最后 a的值为 12,
整个表达式的值为 12。可以看到 ∶ (a=3*5)出现在赋值运算符的左侧,因此赋值表达式 (a=3*5)是左值注意,在对赋值表达式 (a=3*5)求解后,变量 a得到值
15执行 (a=3*5)=4*3时,实际上是将 4*3的积 12赋给变量 a,而不是赋给 3*5。
不能写成,
a=3*5=4*3
2009-7-31
3.9 赋值运算符和赋值表达式赋值表达式也可以包含复合的赋值运算符。
如,a+=a-=a*a
分析,此赋值表达式的求解步骤如下 ∶
① 先进行? a-=a *a? 的运算,它相当于a=
a-a *a,a的值为12- 144=- 132。
②再进行? a+=-132? 的运算,相当于a
=a+(-132),a的值为- 132-132= -264。
2009-7-31
3.9 赋值运算符和赋值表达式将赋值表达式作为表达式的一种,使赋值操作不仅可以出现在赋值语句中,而且可以以表达式形式出现在其他语句(如输出语句、循环语句等)中。
如,printf("%d",a=b);
分析,如果 b的值为 3,则输出 a的值 (也是表达式 a=b
的值 )为 3。在一个语句中完成了赋值和输出双重功能。
2009-7-31
3.10 逗号运算符和逗号表达式逗号运算符,将两个表达式连接起来,又称为? 顺序求值运算符?
如,3+ 5,6+8
一般形式,表达式1,表达式2
求解过程:
先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。
逗号表达式 的值为 14
2009-7-31
3.10 逗号运算符和逗号表达式例,逗号表达式 a=3 *5,a *4
分析,赋值运算符的优先级别高于逗号运算符,因此应先求解a=3 *5。
a的值为1 5,
然后求解a *4,
得60。整个逗号表达式的值为60。
一个逗号表达式又可以与另一个表达式组成一个新的逗号表达式如,(a=3 *5,a *4),a+5
先计算出a的值等于15,再进行a *4的运算得 60(但a
值未变,仍为 15),再进行a+5得20,即整个表达式的值为20。
2009-7-31
3.10 逗号运算符和逗号表达式逗号表达式的一般形式可以扩展为表达式1,表达式2,表达式3,……,表达式n
它的值为表达式n的值。
逗号运算符是所有运算符中级别最低的例,① x=(a=3,6 *3)
② x=a=3,6 *3
赋值表达式,
将一个逗号表达式的值赋给
x,x的值等于18
逗号表达式,包括一个赋值表达式和一个算术表达式,
x的值为3,整个逗号表达式的值为
18。
2009-7-31
3.10 逗号运算符和逗号表达式注意,并不是任何地方出现的逗号都是作为逗号运算符。例如函数参数也是用逗号来间隔的。
如,printf(“%d,%d,%d”,a,b,c);
“a,b,
c”并不是一个逗号表达式,它是
printf函数的
3个参数printf(“%d,%d,%d”,(a,b,c),b,c)
“(a,b,
c)”是一个逗号表达式,
它的值等于c
的值。