C语言的语法基础
2.3.5赋值运算
1。赋值运算符和赋值表达式
C语言中“=”是赋值运算符,赋值号左边必须是变量(或是某种特定的代表存储单元的表达式,详见第五章指针),右边是一个合法的C语言表达式,由此构成赋值表达式,其一般形式如下:
变量名=表达式
赋值运算的功能是先计算“=”号右边表达式的值,然后把这个值赋值给“=”左边的变量,
也就是把“右边表达式的值”存入“左边变量”的地址所指的存储单元中。例如表达式: i=123是将常量123赋值给变量i。
赋值表达式本身有值,它的值为左边变量所得到的新值。赋值运算符的结合方向是“从右到左”。例如赋值表达式:i=j=3*5 的求解过程是,先求解赋值表达式j=3*5, 计算右边3*5的值为15,然后把15赋值给变量j, 由于赋值表达式j=3*5本身值为15, 因此再求解表达式i=15,把15赋值给变量i。这相当于用连等的方式给多个变量赋同一值。
C语言中赋值运算符的优先级仅高于逗号运算符,低于其它运算符。
C语言中字符类型(char)数据取值范围为-128~127,无符号字符类型(unsigned char)数据取值范围为0~255。例如变量ch与ch1定义如下:
char ch;
unsigned char ch1;
若将ASCII码值大于127(0x7f)的字符赋值给ch将被认为是负数。这是因为当ASCII码值大于0x7f时,该字节的最高位为1,系统认为该数为负数。因此处理大于0x7f的ASCII码字符(例如汉字码)时,使用 unsinged char类型的变量ch1较好。
2. 复合赋值运算
在赋值运算符“=”的左边加上算术运算符或位运算符就构成了复合赋值运算符。它们有十种: *=,/=,%=,+=,-=,>>=,<<=,&=,∧=,|=。所有复合赋值运算符的运算优先级都与赋值运算符“=”的运算优先级一样。结合方向也均为“从右到左”。例如:
i-=5 等价于 i= i-5 (可以理解为 i-= 5 即把“i-”放到等号“=”右边)
j*=k-3 等价于j= j*(k-3) (可以理解为j*= (k-3) 这里的括号是必须的,注意不要
写成j=j*k-3 )
[例2.5]以下通过一个例子来说明复合赋值运算的用法。
main()
{
int i=5;
i+=i*=i+6;
printf("i=%d\n",i);
}
运行结果:
i=110
分析表达式i+=i*=i+6的执行过程:
① 结合方向是“从右到左”,先计算i+6的值为11;计算后i的值不变仍为5;
② 再计算i*=11, 相当于i=i*11,因此i=5*11, i的值变成55;
③ 最后计算i+=55, 相当于i=i+55, 因此i=55+55, i的值最后变成110。
3. 赋值运算中的类型转换规则
在算术赋值运算中,当赋值号右边表达式值的“数据类型”与左边“变量的类型”不一致但都是数值型时,系统将自动地把右边的数值类型转换成左边变量的类型后再进行赋值。转换规则如下:
(1)将实型数据赋值给整型变量时,舍弃实数的小数部分。例如i为整型变量,则执行语句i=56.78;之后i的值为56。
(2)整型数据赋值给实型变量时,数值不变,但以浮点数据形式存储到变量中。例如f为float型变量,则执行语句f=123;是先将123转换成实型数据123.0000,并补足精度,再赋值给实型变量f。
(3)整型数据、字符型数据赋值给不同类型的整型变量、字符变量的规则如下,
① 无符号unsigned类型与有符号类型之间的赋值转换规律
若“变量”与“数据”占内存空间的字节数相同,则进行原样赋值;若“数据” 的字节数不足,则高位补0;“数据”的字节数太长,则截取低位。表2.17描述了具体转换规则。
表2.17 无符号数unsigned类型与有符号类型之间的赋值转换规则
本栏相同行上“变量”与“数据”占内存的字节数相同,进行原样赋值 | 本栏相同行上“数据”占内存的字节数太长截取低位, |
本栏相同行上“数据”占内存的字节数不足高位补0 char 原样
原样unsigned charchar截取低位
高位补0unsigned int intunsigned intchar或intunsigned long longunsigned longunsigned charint或long unsigned intlong
[例2.6]以下举例说明无符号unsigned类型与有符号类型之间的赋值转换规则。
main()
{
int i=-5, j=0x9961, k;
unsigned char ch;
unsigned int u;
u=i;
ch=j;
k=ch;
printf("u=%x,u=%u,ch=%c,k=%d\n", u, u, ch, k);
}
运行结果:
u=fffb,u=65531,ch=a,k=97
上例的三条赋值语句的赋值过程如图2.8所示
变量u占2字节,值为0xfffb(即无符号数65531) 变量i占2字节,值为-5
11111111 11111011 11111111 11111011
原样赋值
变量ch占1字节,值为'a' (即0x61) 变量j占2字节,值为0x9961
01100001 10011001 01100001
截取低位
变量k占2字节,值为0x61 (即97) 变量ch占1字节,值为'a'
00000000 01100001 01100001
高位补0
图2.8 无符号unsigned类型与有符号类型之间的赋值转换规则
② 有符号类型与有符号类型之间的赋值转换规律
“数据”占内存的字节数不足“变量”占内存的字节数,则进行符号扩展(负数高位全补1,正数高位全补0);“数据”占内存的字节数太长,则截取低位。表2.18描述了具体转换规则。
表2.18 有符号类型与有符号类型之间的赋值转换规律
相同行上“数据”占内存的字节数太长,则截取低位; 相同行上“数据”占内存的字节数不足,则进行符号扩展 |
||
char |
截取低位 符号扩展 |
int或long |
int |
long |
[例2.7] 以下举例说明有符号类型与有符号类型之间的赋值转换规则。
main()
{ int i=-5, k;
char ch;
long int s;
s=i;
ch='a'-32;
k=ch;
printf("s=%ld,ch=%c,k=%d\n", s, ch, k);
}
运行结果:
s=-5,ch=A,k=65
上例中的三条赋值语句的赋值过程如图2.9所示
变量s占4字节,值为-5 变量i占2字节,值为-5
11111111 11111111 11111111 11111011 11111111 11111011
符号扩展
变量ch占1字节,值为'A' (即0x41) 表达式'a'-32值为整型65
01000001 00000000 01000001
截取低位
变量k占2字节,值为0x41 (即65) 变量ch占1字节,值为'A'
00000000 01000001 01000001
符号扩展
图2.9 有符号类型与有符号类型之间的赋值转换规则
发表评论