算术操作符
+ - * / %
- 除了%操作符之外,其他几个操作符都可用于整数和浮点数
- 对于 / 操作符,如果两个操作符都为整数,执行整数除法,(例如:int a = 3 / 5; a 的值为0,而不是0.6,也可以理解为取商;如果想到到一个小数,则,3和5两个必须有一个是浮点数,比如把3改为3.0,a得到的值就是0.6;但需要注意的是,即使把前面的int整形改为float浮点型,结果依然不会变,因为3/5的值就是0;不过是把0放到浮点型的a里面了)而只要有浮点数执行的就是浮点数除法。
- %操作符的两个操作数必须为整数,返回的是整除之后的余数。
位移操作符
<< 左移操作符; >> 右移操作符
举例说明:
int a = 2;
int b = a << 1;
移位操作符移动的是二进制位;整形a 是4个字节,也就是32个比特位,二进制就是 00000000000000000000000000000010;向左移位,变成了00000000000000000000000000000100;也就是4
右移操作符原理同上;
总结:
左移操作符
左边丢弃,右边补0;
右移操作符
1.算术右移(通常使用的都是算术右移)
右边丢弃,左边补原符号位
2.逻辑右移
右边丢弃,左边补0;
补充:
整数的二进制表示形式其实有三种
原码:直接根据数值写出的二进制序列就是原码。
反码:原码的符号位不变;其他位按位取反就是反码(符号位就是首位,0为正数,1位负数)
补码:反码+1,就是补码
注:对于正整数来说,原码,反码,补码相同,所以这三种形式可以说是针对负整数的。
位操作符
& 按位与
| 按位或
^ 按位异或
注:它们的操作数必须是整数!
举例说明:
int a = 3;
int b = 5;
int c = a & b;
& - 按(二进制)位与
a 的二进制为 00000000000000000000000000000011
b 的二进制为 00000000000000000000000000000101
对应的二进制位内只要有0;按位的结果就为0;只有两个都为1,结果才为1
所以结果为 00000000000000000000000000000001,故 c的值为1
int c = a | b;
| 按(二进制)位或
对应的二进制位有1则为1,两个都为0;结果才为0;故结果为00000000000000000000000000000111;故c的值为7
int c = a ^ b;
^ 按(二进制)位异或
对应的二进制位相同则为0 ,不同则为1;故结果为00000000000000000000000000000110;故c的值为6
注:两个相同的数异或一定为 0 ;0 和任何数异或还是它本身
可是这个操作符到底有什么用呢???
举个例子:
假如交换a,b的值,并且不能创建新的变量
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d; b = %d", a, b);
return 0;
}
这是怎么实现的呢??不难看出,b = a ^ b ^ b; a = a ^ b ^ a ^ b ^ b;两个相同的数异或一定为0;那b不就是等于a ^ 0吗,而且0^任何数都等于它本身,那b 不就等于a的值了嘛!
赋值操作符
赋值操作符一般有:= += -= *= /= >>= <<= %= &= |= ^=
用法也是十分简单
比如 a = a + 10;可以写成 a+= 10;其他的也可以这么理解
需要注意的是: = 一个等号才叫赋值,两个等号叫判断相等
单目操作符
!逻辑反操作符
举例: int a = 5; !a 就为假;假如有一个if语句,if(!a),就不会进入if语句,若a = 0;就可以进入if语句
- 负值
+ 正值
这个就很简单了,举例:int a = 1; a = -a; a的值就为-1了。
& 取地址
* 间接访问操作符 (解引用操作符)
这里就写一段代码来解释把,更加直观一点
#include<stdio.h>
int main()
{
int a = 10;
printf("%p\n", &a);// & - 取地址操作符
int* pa = &a;// pa是用来存放地址的 - pa就是一个指针变量
*pa = 20; // * 解引用操作符 - 间接访问操作符
printf("%d", *pa);
return 0;
}
sizeof 操作数的类型长度(以字节为单位)
举例:int a = 10; siezof(a) ,计算a所占的空间大小,单位是字节,a是整形,所以就是4个字节。
需要注意的是:sizeof是一个操作符,并不是一个函数。
补充一个知识点:计算机储存数据的最小单位是 位(bit),一个位只能表示0和1两种状态,然后便是字节(byte),1字节等于8个位,字节是最基本的数据单位,8位二进制数为1字节,然后便是我们熟悉的kb,mb,gb,tb,pb。
1 byte = 8 bit , 1 kb = 1024 byte 1mb = 1024 kb 1gb = 1024 mb 1tb = 1024 gb 1pb = 1024 tb.
~ 对一个数的二进制按位取反
原理:对一个数的二进制位,0变成1,1变成0;符号位(首位)也要变!
举例:int a = -1; int b = ~a; 我们知道负数在内存中放的是补码,-1的补码是11111111111111111111111111111111,按位取反就是00000000000000000000000000000000,则b的值就为0;
注: 为什么不把这个操作符放到位操作符呢??因为它的操作数只能有一个,而位操作符的操作数有两个,所以~属于单目操作符!
-- 前置 后置--
++ 前置 后置++
前置的效果是先++后使用,后置是先使用,后++ ,–也是这个逻辑
(类型) 强制类型转换
文如其名
举例:int a = 3.14,如果直接这样赋值,会提示把浮点数3.14放到整形a里面可能会丢失数据;这时我们便需要强制类型转换,int a = (int)3.14;
关系操作符
常用的关系操作符有:> < >= <= == !=
这些操作符的使用就更加简单了,一般使用在if语句啊,循环语句啊,需要有判断条件的地方。
需要注意的是 :
1 . = = 不要写成 = ,这两个的意思可是大相庭径!
2 . 比较两个字符串是否相等,不能使用 = =
逻辑操作符
&& 逻辑与 (A 和 B都为真,结果才为真,其中一个为假,结果便为假)
|| 逻辑或 (A 和 B其中一个为真,结果就为真,两个都为假,结果才为假)
注意:
区分 逻辑与和按位与,&&逻辑与,&按位与,逻辑或和按位或 || 逻辑或,|按位或
再讲一下逻辑操作符运算规则,看一个面试题
#include<stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("%d%d%d%d%d", i, a, b, c, d);
return 0;
}
结果为0,1,2,3,4,因为在 逻辑与 操作符运算时,从左往右看,a = 0;第一个就为假,就不再往后运算了。如果第一个不为假,才会继续往右边看。
#include<stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("%d%d%d%d%d", i, a, b, c, d);
return 0;
}
结果为1,1,3,3,4,在逻辑或 操作符在运算时,左右两边如果有一个为真就不会往右边继续运算 了,a为假,往右看,b为真,就不再看d了,所以d的值依然为4
条件操作符
表达式为 : (A) ? (B) : (C)
条件操作符又被称为三目操作符(有三个操作符)
举例: b = a > 5 ? 1 : -1; 意思就是a大于5的话,就给b赋值为1,否则就赋值为-1。
逗号表达式
逗号表达式,就是用逗号隔开的多个表达式。逗号表达式,从左往右依次执行,整个表达式的结果是最后一个表达式的结果。
举例:
#include<stdio.h>
int main()
{
int a = 3;
int b = 5;
int c = 0;
int d = (c = 5, a = c + 3, b = a - 4, c += 5);
printf("%d%d%d%d", a, b, c, d);
return 0;
}
结果为 8 ,4 ,10, 10,d 的值是最后一个表达式的结果,但是并不是说中间就不用计算了,还是要从左往右依次计算。只是结果取最后一个表达式的
下标引用,函数调用和结构成员
1. []下标引用操作符
操作数:一个数组名+一个索引值
举例:
int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符
[]的两个操作数便是 arr 和 9。
2.()函数调用操作符接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
举例:
// 函数的定义
int Add(a, b)
{
int c = 0;
c = a + b;
return c;
}
int main()
{
int a = 1;
int b = 2;
// 函数的调用
int ret = Add(a, b);// 这个括号便是叫函数调用操作符;
return 0;
}
操作数便是函数名Add和传参的数a,和b
3.结构成员访问操作符
. 结构体.成员名
-> 结构体指针 -> 成员名
. 可以访问结构体内的成员。
举例:
假如这里有一本书:书名,书号,价格
创建一个自定义的类型
#include<stdio.h>
//创建一个自定义类型
struct Book
{
// 结构体的成员
char name[20];
char id[20];
int price;
};
int main()
{
struct Book a = { "C语言","C123151293451",30 };
printf("书名:%s\n", a.name);//这个点便是访问结构体内的数组name;
struct Book* p = &a;
printf("书名:%s\n", (*p).name);
printf("书名:%s\n", p->name);// 这两个的结果是一样的,用哪种方法都行
return 0;
}