C中的表达式求值

目录

一、整型提升

二、算术转换

三、操作符属性

四、总结


一、整型提升

C语言中,整型算术运算是在CPU的整型运算器上进行的。而整型运算器内操作数的字节长度一般是普通整型(即int)的字节长度,因此,整型运算时字节长度小于int的操作数都要在提升为普通整型后运算。

整型提升的规则:按照数据的符号位提升

例如:

#include<stdio.h>
int main()
{
   char a = 127;
   char b = 3;
   char c = a + b;
   printf("%d\n",c);

   return 0;
}

由于a、b均属于char类型,在内存中占一个字节,因此:

a的补码:0111 1111

b的补码:0000 0011

按符号位整型提升后,

a的补码: 00000000000000000000000001111111

b的补码: 00000000000000000000000000000011

 a+b得到:00000000000000000000000010000010

由于c属于char类型,进行截断,得到:

c的补码:1000010

c的反码:1000001

c的原码:11111110

c的值:-126

二、算术转换

当一个操作符的操作数数据类型不同时,需要其中一个操作数转换成另一个操作数的类型,否则运算就无法进行。这就是算术转换。

算术转换的方向:

int -> unsigned int -> long int -> unsigned long int -> float -> double -> long double

三、操作符属性

影响表达式求值有三个因素:

  1. 操作符优先级
  2. 操作符结合性
  3. 是否控制求值顺序

判断相邻操作符先执行哪个,要看操作符的优先级,比如我们从小学就知道的先乘除后加减;

如果操作符的优先级相同,就要看操作符的 结合顺序,是从左向右还是从右向左?例如下面:

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a++, --b, a + b); //逗号表达式的结合性是从左向右依次进行

	printf("%d\n", c);   //c = 3
	return 0;
}

不过即使已经知道了操作符的优先级和结合性,我们也不一定能断定这个表达式没有问题。如下:

#include<stdio.h>
int main()
{
	int a = 2;

	int c = (a++) + (++a) + (++a);
	printf("%d\n", c);
	return 0;
}

 在上面的代码中,我们已经预先知道它们的优先级后缀++ > 前缀++ > +,但我们却无法确定这个表达式是先算完a++,++a,++a,最后再相加,还是先算a++,++a的和,再算后面的,由于这个表达式的计算路径不是唯一的,所以这个表达式是有问题的。

关于操作符是否控制求值顺序,只有三个操作符可以控制求值顺序:

  1. 逻辑操作符与(&&):(exp1) && (exp2),当exp1为假时,整个表达式为假,不执行exp2,直接进行后面的操作;
  2. 逻辑操作符或(| |):(exp1) || (exp2),当exp1为真时,整个表达式为真,不执行exp2;
  3. 条件操作符:(exp1) ? (exp2) :(exp3),当exp1为真时,执行exp2;否则,执行exp3.

四、总结

C语言中的表达式求值,就要注意两个方面:一是数据类型的转换,包括整型提升、算数转换;二是操作符的属性,看操作符的优先级和结合性等。通过操作符的属性,我们如果不能确定表达式有唯一计算路径,那么这个表达式就是有问题的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值