C语言中的运算符
1.1 表达式
定义:由操作数和运算符组成的用于返回一个确定值的式子称为表达式
操作数:参与运算的数据称为操作数
1、常量
2、变量
3、表达式
运算符:用于来表示某种计算方法的符号称为运算符
在C语言中所有运算表达式的结果都是一个右值
左值和右值:针对于赋值运算符 等号(=)而言的
右值(rvalue):只能放在等号的右侧的值称为右值(不能被再次改变)
表现形式:常量、表达式的结果、将亡值、值返回的函数的返回结果
左值(lvalue):既能放在等号左侧也能放在等号右侧的值(可以再被更改的值)
表现形式:变量,堆区申请的空间
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num;
//赋值操作
num = 530;
//此行等号将会报错,520作为rvalue无法放在左侧
//520 = num;
int key;
//lvalue可以放在等号的两侧
key = num;
return 0;
}
C语言支持的运算符:单(单目)、算(算数)、关(关系)、逻(逻辑)、条(条件表达式)、赋(赋值)、逗(逗号)
单目运算符:只有一个操作数参与就能完成的运算符。例如 -num
双目运算符:需要使用两个操作数参与的运算符。例如 3*5
三目运算符:需要三个操作数参与的运算符。例如 (?:)
1.2 赋值运算符
定义:将等号右侧的值赋值给等号左侧变量的操作,称为赋值运算
注意:
1、要求等号左侧必须是左值
2、等号右侧左右值均可
3、赋值运算是有方向的,将等号右侧的结果放到等号左侧的容器中
4、赋值运算的结果是一个右值
5、一个表达式中出现多个赋值运算,赋值运算的方向是从右向左结合
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num1 = 520;
int num2 = 1314;
int num3;
num3 = num2 = num1; //合法,运算结束后均为520
(num3 = num2) = num1; //C语言中非法,括号里赋值结束后是一个右值
printf("num1 = %d, num2 = %d, num3 = %d\n", num1, num2, num3);
return 0;
}
赋值运算符的分类
1、普通运算符:=
2、复合运算符:+=、-=、%=、/=、*=、&=、|=......
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 5;
num += 3; //num = num + 3; 复合赋值运算
printf("num = %d\n", num); //8
int key = 3+5; //普通赋值运算
//当赋值运算与算术运算符混合运算时优先计算算术运算符
num *= key+2; //同上
printf("num = %d\n", num); //80
return 0;
}
1.3 算术运算符
功能:执行有关算术相关的计算
种类:+、-、*、/(除法)、%(取余)
优先级:乘除模的优先级高于加减,同一优先级之间的运算,由左向右结合
有关除运算
1、如果除法运算两侧没有实型数据出现,则结果会对商取整
2、如果出现了实型数据,则结果也为实型数据
3、一个整数除以10,表示去掉这个数的个位数
4、一个整数除以一个比自己大的整数,结果为零
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 5;
int key = 2;
double value = 2.0;
printf("num / key = %d\n", num/key); //2
printf("sizeof(num/key) = %zd\n", sizeof(num/key)); //4
printf("num / value = %.2lf\n", num/value); //2.50
printf("sizeof(num/value) = %zd\n", sizeof(num/value)); //8
printf("512 / 10 = %d\n", 512/10);
return 0;
}
上述代码中需要使用sizeof才可以正确观测结果,printf输出的结果是自己定义的所以不能正确的观测运算的结果
有关模运算
1、模运算也叫取余运算,表示取得两个数相除的余数部分
2、要求:%运算符两侧只能是整数,不能出现小数
3、一个数对N取余,结果为[0,N-1]
4、一个数对N取余,结果为0,则该数可以被N整除
5、一个数对2取余,结果只能是0或1,为0时该数为偶数,为1时该数为奇数
6、一个数对10取余,即读取该数的个位数
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 52;
int key = num % 5;
printf("key = %d\n", key);
//key = num%3.00; 不能出现小数
key = num%4;
printf("key = %d\n", key); // 0 可以被4整除
key = num%2;
printf("key = %d\n", key); // 0 偶数
key = num%10;
printf("key = %d\n", key); // 2 取得num的个位数
return 0;
}
练习:
定义一个整形变量存储数据 523, 通过相关运算,将该数据翻转一下,变成325并输出
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 523;
printf("num = %d\n", num);
//分别取得每个位上数值再乘上翻转后对应的权值
num = (num/100) + (num%100/10)*10 + (num%10)*100;
printf("num = %d\n", num);
return 0;
}
1.4 关系运算符
功能:用于判断两个操作数大小关系的运算符,并返回真假值
运算符种类:>、<、==、<=、>=、!=
关系运算符的结果是一个能够表示真假的整数,0表示关系不成立, 1表示关系成立
在C语言中非零即为真
关系运算符的结合顺序是由左向右
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 0;
printf("%d\n", 3 > 5); //0
printf("%d\n", 3 <= 5); //1
printf("%d\n", 3 == 5); //0
printf("%d\n", 3 >= 3); //1
printf("%d\n", 3 != 5); //1
printf("%d\n", 3 + 3 != 5); //1 算术运算符的优先级高于关系运算符
printf("%d\n", num = 3 == 5);
//0 关系运算符的优先级高于赋值运算符
//此处输出的并不是num变量中的值,而是赋值运算结果的临时值
printf("%d\n", 3 > 1 != 1); //0 关系运算符的结合顺序是由左向右
printf("%d\n", num+5 > 2+3 ); //0 算术运算符的优先级高于关系运算符
return 0;
}
1.5 逻辑运算符
定义:表示两个操作数之前的逻辑关系
种类:逻辑与(&&)、逻辑或(||)、逻辑非(!)
并且 和、或者 反之
逻辑运算的结果与关系运算相同,成立为1,不成立为0
p | q | p && q | p || q | !p |
0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 1 | 1 | 1 | 0 |
总结:
逻辑与:全真则真,有假则假
逻辑或:有真则真,全假则假
逻辑或:非真即假,非假即真
逻辑与和逻辑或都有短路状态
对于逻辑与如果第一个表达式不成立则整个表达式为假
对于逻辑或如果第一个表达式成立则整个表达式为真
第二个表达式就不予执行了(被短路掉了)
逻辑非属于单目运算符拥有较高的优先级
#include <stdio.h>
int main(int argc, const char *argv[])
{
//逻辑与:全真则真,有假则假
printf("%d\n", 3 > 5 && 3 != 3); //0 && 0 ----> 0
printf("%d\n", 3 > 5 && 3 == 3); //0 && 1 ----> 0
printf("%d\n", 3 < 5 && 3 != 3); //1 && 0 ----> 0
printf("%d\n", 3 < 5 && 3 == 3); //1 && 1 ----> 1
//逻辑或:有真则真,全假则假
printf("%d\n", 3 > 5 || 3 != 3); //0 || 0 ----> 0
printf("%d\n", 3 > 5 || 3 == 3); //0 || 1 ----> 1
printf("%d\n", 3 < 5 || 3 != 3); //1 || 0 ----> 1
printf("%d\n", 3 < 5 || 3 == 3); //1 || 1 ----> 1
//逻辑非:非真即假,非假即真
printf("%d\n", !(3 < 5)); // !1 ----> 0
printf("%d\n", !(3 > 5)); // !0 ----> 1
printf("------------------------------------\n");
//练习
int num = 1;
int key = 1;
int value = 1;
printf("%d\n", num += num && key == 1 + value); //1
printf("------------------------------------\n");
//逻辑与的短路状态
int a = 1;
int b = 2;
int c = 3;
printf("%d\n", a>b && (c=520)); //第一个表达式为假,第二个表达式不执行
printf("c = %d\n", c);
//逻辑或的短路状态
printf("%d\n", a<b || (c=520)); //第一个表达式为真,第二个表达式不执行
printf("c = %d\n", c);
return 0;
}
1.6 自增自减运算符(--,++)
本质上是对变量进行重新赋值运算
种类:前置自增(自减)、 后置自增(自减)
前置自增:先加1再使用
后置自增:先使用再加1
无论前置还是后置都是单目运算符,拥有较高优先级
只能对左值进行该操作!!
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 5;
int key;
//表达式结束自增就发生了
key = num++ + num++;
// 5 6 在加法发生前num的值就已经是7了
printf("key = %d, num = %d\n", key, num);
return 0;
}
1.7 条件表达式
条件表达式是C语言中唯一一个三目运算符
使用格式:表达式1?表达式2:表达式3
表达式1是一个可以判断真假的表达式,若结果为真执行表达式2,反之执行表达式3
表达式2:表达式1成立时执行的操作,可以是语句也可以是表达式
表达式3:表达式1不成立时执行的操作,同上
条件表达式的结果就是成功执行的表达式的结果
#include <stdio.h>
int main(int argc, const char *argv[])
{
int num = 520;
int key = 1314;
//条件表达式的结果是被执行语句的结果
int value = num>key ? num : key; //1314
printf("value = %d\n", value);
//练习
value = (num++ || key--) >= (key = 520) ? key++ : ++num;
printf("value = %d, num = %d, key = %d\n", value, num, key);
return 0;
}