运算符 一、算术运算符
-
+
加法运算符
把两个操作数相加
int c = 21+10; //c = 31
-
-
减法运算符
第一个操作数减去第二个操作数
int a = 21-10; //a = 11
-
*
乘法运算符
把两个操作数相乘
int b = 21*10; //b = 210
-
/
除法运算符
把两个操作数相除
/
操作数均为整数,结果为取商并取整
int d = 16/5; //d = 3
/
操作数中有一或两个浮点数,结果为取商
double e = 16/5; //e = 3.200000
-
%
取模运算符
整除后的余数操作数都必须为整数,结果取余
注意:“余数”符号和左边操作数相同
int b = 7%3; //b = 1 int c = -7%3; //c = -1 int e = 7%-3; //e = 1
-
++
自增运算符
- 前缀
++a
i = 5;++i; //i = 6; ++i = 6;
- 后缀
a++
i = 5; i++; //i = 6; i++ = 5; `
int a = ++i;
int b = i++;
前缀——先自增后赋值,后缀——先赋值后自增
- 前缀
-
—-
自减运算符
- 前缀
—a
i = 5;—i; //i=4; —i=4;
- 后缀
a—
i = 5; i—; //i=4; i—=5; `
int a = --i;
int b = i–;
前缀——先自减后赋值,后缀——先赋值后自减
- 前缀
关系运算符的结果是逻辑值(真or假)
-
==
等于
判断两个操作数是否相等,如果相等,条件表达式为真,不相等则为假。
例:
5 == 3; 假
5 == 5; 真
-
!=
不等于
判断两个操作数是否不相等,如果不相等,条件表达式为真,相等则为假。
-
>
大于
左操作数是否大于右操作数,如果是,条件表达式为真
-
<
小于
左操作数是否小于右操作数,如果是,条件表达式为真
-
>=
大于等于
左操作数是否大于等于右操作数,如果是,条件表达式为真
-
<=
小于等于
左操作数是否小于等于右操作数,如果是,条件表达式为真
逻辑运算符的操作数只能由逻辑值来充当
0 ——表示逻辑假; 1 (非0值) ——表示逻辑真
-
&&
逻辑与
如果两个操作数都非零,则结果为真
短路原则:当&&
左边的操作数是假,则右边表达式就不需要进行判断,运算结果为假
int a = (12==8 && 4/2==2); //a = 0
-
||
逻辑或
两个操作数都为0,结果为假
短路原则:当||
左边的操作数是真,则右边表达式就不需要进行判断,运算结果为真
int x = 1,y = 1; int t = ++x || ++y; /* 结果是t = 1, x = 2, y = 1 因为++x为真,表达式 ++x || ++y 的结果为真,不用计算++y */
-
!
逻辑非
逆转操作数状态,使真变为假,假变为真。
a=1; //!a为假
(计算机先将输入的十进制数,转换成二进制补码,再进行位运算,然后将二进制结果转换成十进制)
在计算机中操作的是补码
作用于位,逐位进行操作()
以3,5与运算为例演示逐位运算:
文章图片
真值表:
文章图片
例:a = 60; b = 13;
二进制补码: a = 00111100; b = 00001101;
正整数的补码与原码相同,负整数的补码是将原码除符号位外的所有位取反后加1
······································································································································
-
&
与运算符
按”位与“操作,按二进制位进行”与“运算。
都1才1 1&1 = 1
a&b = 00001100
-
|
或运算符
按”位或“操作,按二进制位进行”或“运算。
都0才0 0|0 = 0
a|b = 00111101
-
^
异或运算符
按二进制位进行”异或“运算。
相同为0,不同为1
1^0=1; 1^1=0; 0^0=0
a^b = 00110001
-
~
取反运算符
按二进制位进行”取反“运算。
按位取反:二进制每一位取反,0变1,1变0。
对所有整数取反=本身的相反数-1
计算步骤:(~b为例)二进制数在内存中以补码的形式存储。
转二进制:00001101
计算补码:00001101
按位取反:11110010
转为原码:10001110(负整数反码转原码,将反码减1后除符号位外的所有位取反)
符号位为1是负数,即-14
-
<<
二进制左移运算符
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
a<<2 00111100 → 11110000
-
>>
二进制右移运算符
将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
a>>2 00111100 → 00001111
给变量赋值
基本赋值运算符
=
把右边操作数的值赋给左边操作数(符号=的左边该是一个可修改的变量名,而右边是赋给该变量的值。)int a = 12;
复合赋值运算符
+=
加且赋值运算符把右边操作数加上左边操作数的结果赋值给左边操作数
a += 12;
//→ a = a+12;
-=
减且赋值运算符把左边操作数减去右边操作数的结果赋值给左边操作数
a-=12;
//→ a = a-12;
*=
乘且赋值运算符把右边操作数乘以左边操作数的结果赋值给左边操作数
a *= 12;
//→ a = a*12;
/=
除且赋值运算符把左边操作数除以右边操作数的结果赋值给左边操作数
a /= 12;
//→ a = a/12;
%=
求模且赋值运算符求两个操作数的模赋值给左边操作数
a %= 12;
//→ a = a%12;
<<=
左移且赋值运算符a <<= 2;
//→ a = a<<2;
>>=
右移且赋值运算符a >>= 2;
→ a = a>>2;
【C语言|C语言——运算符】
&=
按位与且赋值运算符a &= 2;
//→ a = a&2;
^=
按位异或且赋值运算符a ^= 2;
//→ a = a^2;
|=
按位或且赋值运算符a |= 2;
//→ a = a|2;
六、其他运算符
-
? :
条件运算符(三元运算符)
先判断?前面的条件表达式的逻辑值,如果为真,结果为?后面的表达式的运算结果;如果为假,则结果是:后面的表达式的运算结果。
x>y ? x : y
若x>y,则结果为x
若x -
&
取地址运算符
返回变量的地址
求某个变量的地址,如scanf()中的&a表示求a的内存空间地址。
int a; scanf("%d",&a);
-
*
指针运算符
指向一个变量
求某个内存地址中的数据。
int* a; int var=20; a = &var; printf("%d",*a); //结果为20
-
,
逗号运算符
当顺序点用,结合顺序是从左至右按顺序求值,完毕后,整个表达式的值是最后一个表达式的结果。
a=(12+6,7/8,9+3); //结果:a=12;
-
sizeof()
求字节数运算符
返回变量的大小,用于求一个对象或者类型所占的内存字节数。
- 语法:sizeof有两种语法:
sizeof(type_name); //sizeof(类型);
sizeof object; //sizeof对象
例:
sizeof(int) = 4;
- 当为数组的时候,sizeof的值=数组元素类型 x 元素个数;
例:
int a[2] = {0,1}; sizeof(a); //4x2=8;
- 总结
sizeof(数组): 分配的数组空间大小;
sizeof(指针): 该指针所用的空间大小(在32位系统是4,在64系统是8);
sizeof(类型): 该类型所占的空间大小;
sizeof(对象): 对象的实际占用空间大小;
sizeof(函数): 函数的返回类型所占的空间大小。函数的返回类型不能是void
- sizeof()和strlen()的区别:
- sizeof求的是占用内存的大小,strlen求的是字符串的实际长度;(sizeof统计’\0’,strlen不统计’\0’)
- sizeof是运算符,strlen是函数;
- sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以’’\0’'结尾的; (sizeof还可以用函数做参数)
- 数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,
- 特点
1、sizeof是运算符,不是函数。sizeof以byte为单位返回操作数的大小。
2、sizeof不能求得 void 类型的长度。
3、sizeof能求得 void * 类型的长度。
4、sizeof能求得静态分配内存的数组的长度。
5、sizeof不能求得动态分配的内存的大小!
6、sizeof不能对不完整的数组求长度!
7、当表达式作为sizeof的操作数时,它返回表达式的计算结果的类型大小,但是它不对表达式求值!
8、sizeof可以对函数调用求大小,并且求得的大小等于返回类型的大小,但是不执行函数体。
9、sizeof求得的结构体(及其对象)的大小并不等于各个数据成员对象的大小之和!
10、sizeof不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小!
- 语法:sizeof有两种语法:
-
(类型)
强制类型转换运算符
一般形式:(类型名)(表达式\常量\变量)
例:
(int)(x+y) //将x+y的值转换为整型(float)(5%3)//将5%3的值转换成单精度型
注意:
- (int)(x+y)与(int)x+y 意义不同,前者先做x+y操作再转换,后者先转换x类型再+y
- 类型转换得一个中间值,原变量类型没有发生变化。
例:
double a = 4.6; int b = (int)a; printf("a=%lf,b=%d", a, b); //结果:a=4.600000,b=4`
- (int)(x+y)与(int)x+y 意义不同,前者先做x+y操作再转换,后者先转换x类型再+y
-
[]
下标运算符
具有两个操作数的双目运算符。
- 指向Type型对象的指针
- 整数类数据类型下标运算符[ ]的操作数的顺序是随意的。
- 下标运算符所生成的值的类型是 Type型
a[5] = 4; int b[10] = {0}; double c[2][2] = {1.0,2.0,3.0,4.0};
-
()
函数调用运算符
return_type function_name**(** parameter list )
void example(); //无返回类型,无形参 int student( int id, char sex ); //int返回类型,有形参
-
_>
间接成员运算符
_>
用于结构体指针,指向该结构的指针访问结构的成员
如
struct Books *struct_pointer; //定义结构体指针 struct_pointer -> title; //指针指向结构体成员title
-
.
结构体访问成员运算符
.
用来访问结构体,共用体中的成员
访问成员的一般形式是: 结构变量名 . 成员名
student.pwd = 12345; //访问student结构体成员pwd,并赋值
推荐阅读
- C语言经典例题|【C语言典例】——day11(统计二进制中1的个数)
- 【C进阶】内功修炼秘籍|【C进阶】two -> 指针进阶
- C语言经典例题|【C语言典例】——day10(杨氏矩阵)
- 数组与指针进阶|指针进阶-ONE(包含对数组的加深理解)
- 数组与指针进阶|指针进阶-TWO
- 数组与指针进阶|指针进阶-THREE(有对指针和数组的加深理解)
- 单片机|单片机学多久能工作,单片机学好了能应聘什么工作()
- 单片机|单片机值得学吗(会单片机能找什么工作?)
- C语言系列|C语言如何把多位数的每一位提取出来,(例如(四位数2345,把个、十、百、千位提取出来)超级详解)