运算符
一、算术运算符
-
+
加法运算符把两个操作数相加
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=0a^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;
&=
按位与且赋值运算符
a &= 2; //→ a = a&2;
^=
按位异或且赋值运算符
a ^= 2; //→ a = a^2;
|=
按位或且赋值运算符
a |= 2; //→ a = a|2;
六、其他运算符
-
? :
条件运算符(三元运算符)先判断?前面的条件表达式的逻辑值,如果为真,结果为?后面的表达式的运算结果;如果为假,则结果是:后面的表达式的运算结果。
x>y ? x : y
若x>y,则结果为x
若x<y,则结果为y
-
&
取地址运算符返回变量的地址
求某个变量的地址,如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不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小!
-
-
(类型)
强制类型转换运算符一般形式:
(类型名)(表达式\常量\变量)
例:
(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`
-
-
[]
下标运算符具有两个操作数的双目运算符。
- 指向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,并赋值