老汤回味——C语言运算符及类型转换

时间:2023-01-28 20:47:29

今天的文章一起来看看C语言的运算符,而和C语言运算符直接相关的一个问题就是类型转换。下面先来看看C语言有哪些运算符。


算数运算符

算数运算符包括:加(+),减(-),乘(*),除(/),取余(%),自增(++),自减(--),下面上代码,直接看例子。

#include <stdio.h>

int main(void)
{
	int a = 10;
	int b = 2;
	printf("a + b = %d\n", a + b);
	printf("a - b = %d\n", a - b);
	printf("a * b = %d\n", a * b);
	printf("a / b = %d\n", a / b);
	printf("a %% b = %d\n", a % b);
	printf("a++ = %d, ++a = %d\n", a++, ++a);
	printf("b-- = %d, --b = %d\n", b--, --b);

	int c = a++;
	int d = a--;
	printf("c = %d\n", c);
	printf("d = %d\n", d);

	return 0;
}

运行结果:

a + b = 12
a - b = 8
a * b = 20
a / b = 5
a % b = 0
a++ = 11, ++a = 12
b-- = 1, --b = 0
c = 12
d = 13


需要说明的有以下几点:

  1. %运算符只可以用于两个整型;

  2. a++和++a在打印时没有差别,但是将其赋值给变量时,存在差别,如上例中的c和d,a++是先将a赋值给变量,之后才会做自增;++a则是自增后将值赋值给变量。--运算符与++运算符类似。


关系运算符

关系运算符用来比较两个数的大小,包括:等于(==),不等于(!=),大于(>),大于等于(>=),小于(<),小于等于(<=),看一下例子。

#include <stdio.h>

int main(void)
{
	int a = 1;
	int b = 2;
	printf("a == b: %d\n", a == b);
	printf("a != b: %d\n", a != b);
	printf("a < b: %d\n", a < b);
	printf("a <= b: %d\n", a <= b);
	printf("a > b: %d\n", a > b);
	printf("a >= b: %d\n", a >= b);

	return 0;
}
运行结果:

a == b: 0
a != b: 1
a < b: 1
a <= b: 1
a > b: 0
a >= b: 0


可以看到,C语言中使用0和1分别代表false和true。


逻辑运算符

逻辑运算符包括:逻辑与(&&),逻辑或(||),逻辑非(!)。

#include <stdio.h>

int main(void)
{
	int a = 1;
	int b = 2;
	int c = 3;
	printf("a > b && c > b: %d\n", a > b && c > b);
	printf("a > b || c > b: %d\n", a > b || c > b);
	printf("!(a > b): %d\n", !(a > b));

	return 0;
}

运行结果:

a > b && c > b: 0
a > b || c > b: 1
!(a > b): 1

需要说明的是,逻辑运算符存在短路的机制,比如上面的第一句printf,由于a>b为false,此时逻辑与已经不可能为true,所以后面的c>b将不会运行,也就是说逻辑与会被第一个为false的条件表达式所阻断;同理,对于逻辑或,如果前面的条件表达式已经为true,则无论后面的条件表达式为true或者false都对结果无关紧要了,逻辑或将会执行到第一个为true的条件表达式。


位运算符

位运算符操作整型的位,包括:按位与(&),按位或(|),异或(^),按位取反(~),左移(<<),右移(>>)。

#include <stdio.h>

int main(void)
{
	int a = 1;
	int b = 4;
	printf("a = 0x%08x\n", a);
	printf("b = 0x%08x\n", b);

	printf("a & b: 0x%08x\n", a & b);
	printf("a | b: 0x%08x\n", a | b);
	printf("a ^ b: 0x%08x\n", a ^ b);
	printf("~a: 0x%08x\n", ~a);
	printf("a << 2: 0x%08x\n", a << 2);
	printf("a >> 1: 0x%08x\n", a >> 1);

	printf("a | (1 << 2): 0x%08x\n", a | (1 << 2));
	printf("b & ~(1 << 2): 0x%08x\n", b & ~(1 << 2));

	return 0;
}

运行结果:

a = 0x00000001
b = 0x00000004
a & b: 0x00000000
a | b: 0x00000005
a ^ b: 0x00000005
~a: 0xfffffffe
a << 2: 0x00000004
a >> 1: 0x00000000
a | (1 << 2): 0x00000005
b & ~(1 << 2): 0x00000000


需要说明以下几点:

  1. 左移运算,最高位会移出,低位补0;

  2. 右移运算,低位移出,最高位为1,则为1,为0,则为0,即保留符号位;

  3. 最后两条printf语句,用来演示如何给一个数的第2位置位为1和如何清除一个数第2位的1。


赋值运算符

主要包括=, +=,-=,*=,/=,%=,<<=,>>=,&=,|=,^=,除了=运算符,其他的都是结合了其他运算符的功能,比如a += 1,就是将a和1相加,再把结果赋值给a,这里不再赘述。


类型转换

C语言是强类型语言,不同类型的数据之间进行运算会进行类型的转换,转换方式主要有两种,强制类型转换和隐式类型转换。


强制类型转换是在编码时通过显式编写代码,实现的类型转换;隐式类型转换则是C语言编译器自动为我们进行的类型转换,总的原则是

  1. 如果表达式中的数据属于同一个大类型,比如都是整型,则数据统一向表达式中宽度最大的转换,如int向long转换,有符号类型还会向无符号类型转换,如int向unsigned int转换;

  2. 整型和浮点型运算,整型会转换为浮点型。

  3. 强制将浮点型转换为整型,浮点型小数部分丢失。


看一个简单的例子

#include <stdio.h>

int main(void)
{
	int a = 1;
	float b = 2.2;
	long c = 12;

	printf("a + c = %ld\n", a + c);
	printf("a + b = %f\n", a + b);
	printf("a + (int)b = %d\n", a + (int)b);

	return 0;
}

运行结果:

a + c = 13
a + b = 3.200000
a + (int)b = 3

老汤回味——C语言运算符及类型转换