一.算数操作符:
+ - * / %
-
+、-、*、/这四个运算符均可用于整数及浮点数的运算。
-
当使用/运算符时,如果两个操作数均为整型,那么执行整数除法,运算结果也为整型;如果两个操作数至少一个为浮点数,那么执行浮点数运算,运算结果为浮点型。
-
%运算符只能用于两个整数相除,返回余数。
二.位移操作符:
<< >>
注:位移操作符的操作数只能是整数
- 左移操作符(<<):不论算术移位还是逻辑移位,均将左边的数舍弃,右边空缺位补0(左边丢弃,右边补0)
- 右移操作符(>>):
当进行逻辑移位时,右边位丢弃,左边空缺位补0(右边丢弃,左边补0) ; 当进行算术移位时,右边位丢弃,左边位补原数的符号位(右边丢弃,左边补符号位)。
拓展:
整数的二进制表示有三种——原码,反码,补码
- 正整数的原码,反码补码相同
- 负的整数的原码,反码,补码是要计算的
- 整数在内存中储存的是补码
(1).例如=>7——由二进制得111,且为正整数(四个字节=32个比特位),所以首位为0
- 原码:00000000000000000000000000000111
- 反码:00000000000000000000000000000111
- 补码:00000000000000000000000000000111
(2)..例如=>-7——由二进制得111,且为负整数(四个字节=32个比特位),所以首位为1
- 原码:10000000000000000000000000000111(首位为1)
- 反码:11111111111111111111111111111000(原码的符号位不变,其他位按位取反)
- 补码:11111111111111111111111111111001(反码+1)
观察代码及其输出结果:
注意:
- 移位操作不改变原值。
- 移位时不能移负数位,这个是标准未定义的
三.位操作符:
& (按位与) | (按位或) ^(按位异或)
注:它们的操作数必须是整数
(1)& 按(二进制)位与
例如(观察代码及其结果):
%d意味着打印一个有符号的数
思路如下:
- 00000000000000000000000000000011—— 3的补码
- 00000000000000000000000000000101—— -5的原码
- 11111111111111111111111111111010—— -5的反码
- 11111111111111111111111111111011—— -5的补码
- 计算方法(比较二者补码,同零为零,同一为一,二者不同为零,最后转化为原码输出)
- 00000000000000000000000000000011——按位与结果,正整数原码和补码相等(转化后结果为3)
(2). | 按(二进制)位或
例如(观察代码及其结果):
思路如下:
- 00000000000000000000000000000011—— 3的补码
- 00000000000000000000000000000101—— -5的原码
- 11111111111111111111111111111010—— -5的反码
- 11111111111111111111111111111011—— -5的补码
- 计算方法(比较二者补码,只要有一为一,同时为零为零,最后转化为原码输出)
- 11111111111111111111111111111011——按位或结果
- 10000000000000000000000000000101——转化为原码,符号位不变(结果为-5)
(3). ^ 按(二进制)位异或
例如(观察代码及其结果):
思路如下:
- 00000000000000000000000000000011—— 3的补码
- 00000000000000000000000000000101—— -5的原码
- 11111111111111111111111111111010—— -5的反码
- 11111111111111111111111111111011—— -5的补码
- 计算方法(比较二者补码,相同为零,相异为一,最后转化为原码输出)
- 11111111111111111111111111111000——按位异或结果
- 10000000000000000000000000001000——转化为原码,符号位不变(结果为-8)
例题:不能创建临时变量(第三个变量),实现两个数的交换
如下图(交换成功):
代码如下:
//异或操作符支持交换律
#include<stdio.h>
int main()
{int a = 3;int b = -5;printf("交换前:a=%d,b=%d\n", a, b);a = a ^ b;//a=3^5b = a ^ b;//b=3^5^5 b=3a = a ^ b;//a=3^5printf("交换后:a=%d,b=%d\n", a, b);
}
四.赋值操作符:
- 赋值运算可以修改一个变量的值(=)
- 复合运算符:+=,-=,*=,%=,>>=,<<=,&=,|=,^=
如下图所示,同理可推理出其他复合运算符的含义
五.单目操作符(只有一个操作数):
- ! 逻辑反操作符
- - 负值
- + 正值
- & 取地址
- sizeof 操作数的类型长度(以字节为单位)
- ~ 对一个数的二进制按位取反
- -- 前置,后置--
- ++ 前置,后置++
- * 间接访问操作符(解引用操作符)
- (类型) 强制类型转换
(上面的操作符基本上前面都已经总结过,除了~)
(1)~(按位取反)
例题: 对一个数的二进制按位取反 (包括符号位)
例如:
#include <stdio.h>
int main()
{int a = -1;//根据前面复习的知识点,易得//10000000000000000000000000000001 - 原码//11111111111111111111111111111110 - 反码//11111111111111111111111111111111 - 补码int b = ~a; //全部按位取反//b的表示应为://00000000000000000000000000000000 //故将a按位取反之后赋值给b的值为0printf("%d\n", a);printf("%d\n", b);return 0;
}
(2)sizeof:操作数的类型长度(以字节为单位)
- sizeof是操作符,不是函数
- strlen是库函数,是用来求字符串长度
- sizeof括号中的表达式是不参与运算的
六.关系操作符:
> < >= <= != ==
- ==是等于,=是赋值,不要混淆!
- !=是不等于,>=是大于等于,<=是小于等于
- 关系运算符就是进行比较,结果为真返回1,结果为假返回0
七.逻辑操作符:
- && 逻辑与
|| 逻辑或
截断特性:逻辑与左边为假,右边不在读取计算 , 逻辑或左边为真,右边不在读取计算
(1)&& 逻辑与
理解为: 即 怎么 又 怎么 , 一假全假,全真为真
(2)|| 逻辑或
理解为: 要么 怎么 要么 怎么 , 一真为真, 全假为假
七.条件操作符(三目操作符):
表达式1?表达式2:表达式3;
- 有三个操作数
- 若exp1假,则输出exp3;若exp1真,则输出exp2
八.逗号表达式:
exp1,exp2,exp3,...expN
- 逗号表达式就是逗号隔开的一串表达式
- 逗号表达式的特点是:从左向右依次计算,整个表达式的结果是最后一个表达式的结果
九.下标引用、函数调用和结构成员
(1)下标引用操作符[ ]
- 操作数:一个数组名+一个索引值
int arr[10];//创建数组 arr[9] = 10;//实用下标引用操作符 [ ]的两个操作数是arr和9
(2)函数调用操作符( )
- 接受一个或多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数
(3)访问一个结构的成员:
- . 结构体.成员名
- -> 结构体指针->成员名
- 结构体普通变量如何访问结构体成员:C语言规定,结构体的普通成员可以通过运算符“点.”去访问其成员
- 结构体指针变量如何访问其成员:可以通过箭头符号的方式去访问其成员
- (*p).name = = p -> name 左右两种方式等价
- 结构体成员如果是字符串,不能直接通过符号“=”去修改值,可以通过C语言中的拷贝函数strcpy去修改值