C语言-操作符(重要)

哈喽,我又来啦,在前面的学习中,我们遇到过很多的操作符,那么每一个操作符都有自己意义,那么今天我们就来了解下吧!(内容有点多哦,加油学!)

首先,操作符大致可分为这几类:算术操作符,位移操作符,位操作符,赋值操作符,单目操作符 ,关系操作符,逻辑操作符,条件操作符,逗号操作符等等,那我们来一个一个了解

算数操作符

算数操作符:+  -  *  /  %(取模)

       案例:

int main()
{
	int a = 5 / 2;
	printf("%d\n", a);
	int b = 5 % 2;
	printf("%d\n", b);
printf("%d\n",11 %  5);
printf("%d\n",-11 %  -5);
printf("%d\n",-11 %  5);
	return 0;
}
  1. int a = 5 / 2:定义一个整型常量a,并且给a赋予5/2的值,此时a会等于5/2的商,也就是2
  2. int b = 5 % 2:定义一个整型常量b,并且给b赋予5%2的值,此时b会等于5/2的余数,也就是1
  3. printf("%d\n",11 %  5);负数求摸,结果符号由第一个运算符的符号决定,故是1,-1,-1

注意:如果除号两边都是定义的整数,那么输出的结果也是整数,如果有浮点数,那么输出的结果就是浮点数,例如:7/2.0f, 此时%f输出的结果会是3.50000,记住让数值变为浮点数一定要加f;另外取模操作符只能用于整型,不能用于浮点数

移位操作符

移位操作符:<<左移操作符,>>右移操作符,移动的是二进制位

案例:

int main()
{
	int a = 1;
	int b = a << 1;
	int c = a << 2;
	printf("%d\n", b);
	printf("%d\n", c);
	return 0;
}

int a = 1:定义一个常量为1的整型a,因为一个整型占用4个字节,也就是32bit位,所以化成二进制就是 00000000000000000000000000000001,结果为1

int b = a << 1:定义一个整型变量b,并赋予值a<<1,意思是将a的二进制位向左移动一位,那么此时二进制为 00000000000000000000000000000010,结果为b=2(十进制)

int c = a << 2:定义一个整型变量c,并赋予值a<<2,意思是将a的二进制位向左移动两位,那么此时二进制为 00000000000000000000000000000100,结果为c=4(十进制)

注意:a的值仍然不改变,依旧是1,改变的b,c的值,右移操作符同理

位操作符

位操作符:& 与运算 、| 或运算、^异或运算

       & 与运算:同为1(真),则为真,否者为0(假),既有房又有车

       | 或运算:有1(真)则真,全为0(假)位0(假),房、车有一即可

       ^异或运算:相同为0(假),不同位1(真)

注意:位操作符是要转化为二进制进行运算的!

案例:

int main()
{
	int a = 3;
	int b = 5;
	int c = a & b;
	int d = a | b;
	int e = a ^ b;
	printf("%d\n", c);
	printf("%d\n", d);
	printf("%d\n", e);
	return 0;
}

赋值操作符

赋值操作符:=  +=  -=  *=  /=  &=  ^=  |=  >>=  <<=

注意:和初始化区别,int a =10 这个等号是初始化,a=20,这里是赋值

补充:赋值支持连续赋值,从右向左以此赋值,例如:a=b=5+7

单目操作符

单目操作符、双目操作符、三目操作符:就是操作符有几个操作数,例如:a+b  其中+就属于双目操作符,因为它一前一后共有两操作数

单目操作符:

!

! 逻辑反操作符:是真取假,是假取真(仅限0)

案例:

int main()
{
	int a = 10;
	int b = 0;
	printf("%d\n", !a);
	printf("%d\n", !b);
	return 0;
}

-  +

- 负值:取负

+ 正值:取正

案例:

int main()
{
	int a = -2;
	int b = -a;
	int c = +2;
	printf("%d\n", a);
	printf("%d\n", b);
	printf("%d\n", c);
	return 0;
}

&

&:取地址操作符

这一个在后面的指针会进行具体讲解……

Sizeof

Sizeof:操作数的类型长度(以字节为单位),计算的是变量/类型所占用空间的大小

案例:

int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(int));
	printf("%d\n", sizeof a);
	printf("%d\n",sizeof int);
	return 0;
}
  1. printf("%d\n", sizeof(a)):以十进制的方式打印sizeof所计算的结果,所以算的是a的大小,结果为4个字节
  2. printf("%d\n", sizeof(int)):以十进制的方式打印sizeof所计算的结果,所以算的是类型int的大小,结果为4个字节
  3. printf("%d\n", sizeof a):效果如第一个一样,sizeof可以计算没有括号的变量
  4. printf("%d\n",sizeof int)不能计算没有括号的类型,故要报错

补充:在上面的案例中编译器可能会提示将%d改成%zd,那是因为szie_t这个类型是专门为sizeof提供的,而这个size_t值默认是unsigned int (无符号整型),所以才会有提示

案例2:

int main()
{
	int x[10] = { 0 };
	int y = 0;
	printf("%d\n", sizeof(x));
	y = sizeof(x) / sizeof(x[0]);
	printf("y=%d\n", y);
	return 0;
}
  1. int x[10] = { 0 }:定义一个长度为10的x数组,并且所有元素初始化为0,也就是x[0]-x[9]为0
  2. printf("%d\n", sizeof(x)):因为一个整型(int)是等于4个字节,又因为x为长度为10的数组,故是10*sizeof(int)=40,最后结果为40
  3. y = sizeof(x) / sizeof(x[0]):计算数组的元素个数,个数=数组总大小/每个元素的大小,所以定义y等于sizeof(x)(数组总大小)来除sizeof(x[0])(第一个元素的大小)
  4. printf("y=%d\n", y):将y的值用y=十进制的形式打印出来,最终结果为10,与最开始的x[10]十个元素符合

注意:sizeof计算终止符\n和空格,和strlen一样

~

~:对一个数的二进制按位取反,取反的是二进制,是0则1,是1则0

案例:

int main()
{
	int a = 0;
	int b = ~a;
	printf("%d\n", b);
	return 0;
}
  1. int a = 0:定义一个值为0的整型变量a,因为一个整型是4个字节,32bit个位,所以a=00000000000000000000000000000000
  2. int b = ~a:定义一个整型变量为b,并将a进行~运算后的值赋予b,因为int默认定义的是有符号数,故将 a取反后第一个是符号标志符,结果是b=11111111111111111111111111111111
  3. printf("%d\n", b):以十进制的方式打印b的值,因为printf打印的是原码,而上面的b符号位是1,也就是负数,又因为整数在存储的时候存储的是补码,故要将b进行:补码→反码→原码 的转换在进行打印,结果为-1

--

--:分为前置、后置—  前置:先--后使用 ;后置:先使用,后—

案例:与下方++原理一样,只是—是相减,然后值不一样 a=9 b=10 x=9 y=9

++

++:分为前置、后置++ 前置:先++后使用 ;后置:先使用,后++

案例:

{
	int a = 10;
	int x = 10;
	int b = a++;
	int y = ++x;
	printf("a=%d b=%d\n", a, b);
	printf("x=%d y=%d\n", x, y);
	return 0;
}
  1. int a = 10int x = 10:定义一个整型变量为a和x,并赋予值10
  2. int b = a++:定义一个整型变量为b,并执行后置++的运算,此时先将a的值赋予b,然后a再进行++,故运算结果a=11,b=10
  3. int y = ++x:定义一个整型变量为y,并执行前置++的运算,此时先将a的进行++,然后将++后的值赋予y,故运算结果x=11,y=11
  4. printf("a=%d b=%d\n", a, b);printf("x=%d y=%d\n", x, y):以十进制的方式打印a、b和x、y的值,并在值前面加上a=、b=和x=、y=

*

*:间接访问操作符(解引用操作符)

这一个在后面的指针会讲到

(类型)

(类型):括号里面放个类型:强制类型转换

案例:

int main()
{
	int a = (int)3.14;
	printf("%d\n", a);
	return 0;
}
  1. int a = (int)3.14:定义一共整型变量为a,并且赋予强制转换符值3.14,意思是,因为int a 是整型变量,而3.14是双精度型的,如果执行的话编译器可能会报错,提示会丢失数据,那在3.14前加前置类型符(int)就表示此3.14强制转化为整型,此时编译器不会报错
  2. printf("%d\n", a):以十进制的形式打印a,此时a=3

补充:EOF:end of file 文件结束标志 值是-1

关系操作符

关系操作符:>    >=    <    <=   !=(不相等)   ==(相等)

注意:关系表达式的结果如果为真,通常为1

案例:容易做错误例子

int main()
{
	int a = 3;
	if (a = 4);
	printf("666");
	return 0;
}
  1. int a = 3:定义一个整型变量为a,初始化为3
  2. if (a = 4):用if语句给a赋值为4
  3. printf("666"):如果if语句为真,则打印666

注意:这里的if语句( )中是赋值不是判断,是将a赋值为4,那么此时a是位真,因为非0,故执行打印,为了避免将判断弄成赋值这种情况,一般将常量写在左边,变量写在右边就好了

还有另外一个需要避免的情况:关系操作符不宜连用

案例:

int main()
{
	int a = 5;
	int b = 5;
	int c = 7;
	if (a < c < b)
		printf("xxxx");
	else
		printf("hhhh");
	return 0;
}
  1. int a = 5;int b = 5;int c = 7:定义变量分别初始化
  2. if (a < c < b):用if进行判断,注意了,因为if是从左到右判断的,所以是这样运行的,先判断a<b,得到结果为真,那么就是1(关系操作符真为1),再将1<b进行判断,结果为真,那么就打印下面的xxxx

如果为避免以上情况,我们可以这样写:

int main()
{
	int a = 5;
	int b = 5;
	int c = 7;
	if (a < c && c < b)
		printf("xxxx");
	else
		printf("hhhh");
	return 0;
}

if (a < c && c < b):在判断中间加上一个 && 而&&是与运算,同为真才为真,那么又因为c<b是为假的,那么这整个表达式都是假,那么就执行else了

逻辑操作符

逻辑操作符:&&逻辑与   ||逻辑或

注意:真-0 -0

&&

&&:逻辑与 同时为真则为真,否则为假

注意:与位操作符的区别,位操作符需要转化为二进制在进行判断,二逻辑操作符可直接判断,判断依据逻辑操作符注意哪一句话

案例:

int main()
{
	int a = 3;
	int b = 5;
	int c = a && b;
	printf("c=%d\n", c);
	return 0;
}
  1. int a = 3;int b = 5:定义一个整型变量为a和b,并赋予值3和5
  2. int c = a && b:定义一个整型变量为c并且将a && b的值赋予c,因为此时是进行逻辑与运算,所以a和b都是真(非0),故此时c 的值也是真,也就是1
  3. printf("c=%d\n", c):将c的值以十进制的方式打印出来,此时是1

||

||:逻辑或 只要有一个为真,就为真,否者为假

注意:与位操作符的区别,位操作符需要转化为二进制在进行判断,二逻辑操作符可直接判断,判断依据逻辑操作符注意哪一句话

案例:

int main()
{
	int a = 3;
	int b = 0;
	int c = a || b;
	printf("c=%d\n", c);
	return 0;
}
  1. int a = 3;int b = 5:定义一个整型变量为a和b,并赋予值3和0
  2. int c = a || bint c = a && b:定义一个整型变量为c并且将a || b的值赋予c,因为此时是进行逻辑或运算,所以a或b中有一个为真(非0),即为真,因为此时a=3,故此时c 的值也是真,也就是1
  3. printf("c=%d\n", c):将c的值以十进制的方式打印出来,此时是
短路

C语⾔逻辑运算符还有⼀个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是 保证的。如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短 路”

如前⾯的代码: if (month >= 3 && month <= 5)

表达式中&& 的左操作数是 month >= 3 ,右操作数是 month <= 5 ,当左操作数 month >= 3 的 结果是0的时候,及时不判断 month <= 5 ,整个表达式的结果也是0(不是春季)。 所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执⾏

对于 || 操作符是怎么样呢?我们结合前⾯的代码:if (month == 12 || month == 1 || month == 2)

如果month == 12,则不⽤再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。 所以, || 操作符的左操作数的结果不为0时,就⽆需执⾏右操作数。 像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进⾏计算的运算称为短 路求值

条件操作符

例:exp1?exp2:exp3

解释:判断exp1的表达式为真或假,如果为真就执行exp2表达式,此时整个表达式的结果就是exp2表达式的结果,如果为假就整型exp3表达式,此时整个表达式的结果是exp3表达式的结果

注意:此函数是三目操作符,共三个操作数

案例:

int main()
{
	int a = 10;
	int b = 20;
	int max = 0;
	max = a > b ? a : b;
	printf("%d\n", max);
	return 0;
}
  1. int a = 10;int b = 20;int max = 0:定一个为a、n、max的整型变量,并且赋予相应的值
  2. max = a > b ? a : b:判断表达一:a>b 的真假
  3. 如果为真,执行a表达式,如果为假,执行b表达式,并且整个表达式的结果就是执行的表达式结果,此时因为a>b为假,故执行b表达式,b表达式结果为20,所以此时整个表达式结果为20,并将值赋予给max
  4. printf("%d\n", max):以十进制的形式打印max,此时结果为20

逗号操作符

例:exp1,exp2,exo3,…expN

解释:逗号操作符可以按照从左到右的顺序进行运算,并且逗号操作符只保留以后一共表达式的结果,最终结果为最后一个表达式的结果,逗号表达式还可以扩展语句

下标引用、函数调用和结构成员

[ ]

[ ]:下标引用操作符

案例:

int main()
{
	int x[10] = { 0 };
	x[4];
	printf("%d\n", x[5]);
	return 0;
}
  1. int x[10] = { 0 }:定义一个为10个数组的整型变量x,并且初始化为0
  2. x[4]:访问(引用)下标为4的x数组
  3. printf("%d\n", x[5]):以十进制的形式打印下标为5的x数组

( )

():函数调用操作符

案例:

调用上面函数的案例

int f(int x, int y)
	{
	int z = x + y;
	return z;
	}
int  main()
{
	int a = 5;
	int b = 6;
	int sum = 0;
	sum = f(a, b);
	printf("sum=%d\n", sum);
	return 0;
}

  1. 此代码调用函数案例中的代码
  2. sum = f(a, b):这一句中的括号( )就是调用操作符,调用上面定义的f函数

好啦,这一章的学习就到这里咯,我们下期再见 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值