一、算术操作符
+ - * / %(取余)
C语言中的 +、 -、 * 都是与数学中的用法一样,这里就不都介绍了,其中 / 与 % 会有一些差异、
1、/(除)
当除号两端都是整数的时候,是按照整数的方式进行运算的,得到的结果是商
当除号的两端有一个是浮点数,是按照浮点数的方式进行运算的,得到的是小数
int main()
{
//当除号两端都是整数的时候,是按照整数的方式进行运算的,得到的结果是商
//当除号的两端有一个是浮点数,是按照浮点数的方式进行运算的,得到的是小数
int a = 10;
int b = 4;
printf("%d\n", a / b); // 2
printf("%lf\n", a / (b * 1.0)); // 2.50000
printf("%lf\n", a / 4.0); // 2.50000
return 0;
}
2、%(取余)
只能用于整数不能用于浮点数
当%两端都是整数的时候,得到的结果是相除之后的余数
int main()
{
// 只能用于整数不能用于浮点数
// 当%两端都是整数的时候,得到的结果是相除之后的余数
int a=10;
int b=4;
printf("%d",a % b); // 2
return 0;
}
二、位移操作符
<<(左移操作符) >>(右移操作符)
【注】位移操作符的操作数只能是整数
移位操作符不能移动负数位
1、<<(左移操作符)
移动的时二进制位,因为在内存中数据是以补码的形式存在的,同理 移动的是二进制的补码
左移操作符如何移动:左边丢弃,右边补0
#include <stdio.h>
int main()
{
//左移操作符 <<
int a = 10;
//a 的原码:00000000 00000000 00000000 00001010
//正数的原码 反码、补码 相同
int b = a << 1;
//将a左移一位:00000000 00000000 00000000 00010100
// 左移一位之后还是一个正数,原、反、补 相同
// b=20
printf("%d\n", b);//20
}
2、>>(右移操作符)
移动的是二进制位 移动的是二进制位的补码
移位规则:
1、算术右移:右边丢弃左边补符号位(大部分编译器都用)
2、逻辑右移:右边丢弃左边补0
#include <stdio.h>
int main()
{
//0 表示正数,1表示负数
int a = -10;
//a原码 : 10000000 00000000 00000000 00001010
// 反码: 11111111 11111111 11111111 11110101
// 补码: 11111111 11111111 11111111 11110110
//将补码算术右移一位
int b = a >> 1;
//补码:11111111 11111111 11111111 11111011
// 10000000 00000000 00000000 00000100
//原码:10000000 00000000 00000000 00000101
// b=-(1+4)=-5
printf("%d\n", b);
return 0;
}
三、位操作符
& | ^ ~
【注】位移操作符的操作数只能是整数
1、&按位与
& 按位与:操作的是二进制的补码,二进制位一位一位的运算
运算规则:两个对应的二进制位只要有0结果为0,只有全为1时结果为1
(有0为0,全为1为1)
判断一个数是否为2的次方:n & (n-1)!= 0
#include <stdio.h>
int main()
{
//&:有0为0 同为1为1
int a = 10;
int b = 20;
int c = a & b;
//正数的 原码、反码、补码相同
//a原码:00000000 00000000 00000000 00001010
//b原码:00000000 00000000 00000000 00010100
//a&b: 00000000 00000000 00000000 00000000
//c=0;
printf("%d\n", c);//0
return 0;
}
2、|按位或
| 按位或:操作的是二进制的补码,二进制位对齐运算
运算规则:对应的二进制位 只要有一个 1 结果为 1 ,都为 0 结果为 0
(有1为1 ,同0为0)
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = a | b;
printf("%d\n", c);
//正数的原码、反码、补码相同
//a的补码: 00000000 00000000 00000000 00001010
//b的补码:00000000 00000000 00000000 00010100
// a | b: 00000000 00000000 00000000 00011110
//c=2+4+8+16=30
printf("%d\n", c);//30
return 0;
}
3、^按位异或
^ 按位异或:操作的是二进制位的补码,二进制位对齐运算
运算规则:二进制位相同为 0 ,二进制位不同为 1
(相同为0,相异为1)
任何数和0异或,结果都是任何数本身
任何数异或其本身 结果都是0
#include <stdio.h>
int main()
{
int a = 0;
int b = 10;
int c = a ^ b;
//正数的原码、反码、补码 相同
//a 补码:00000000 00000000 00000000 00000000
//b 补码:00000000 00000000 00000000 00001010
//c 补码:00000000 00000000 00000000 00001010
//c是正数,原码、反码、补码 相同
//c=10
//总结:任何数 和 0 异或 结果都是其本身
printf("%d\n", c);//10
return 0;
}
4、~按位取反
~ 按位取反:操作的是二进制位的补码
运算规则:将二进制位的 0变成1 ,1变成0
#include <stdio.h>
int main()
{
int a = -1;
int b = ~a;
printf("%d\n", b);
//a:
//原码:10000000 00000000 00000000 00000001
//反码:11111111 11111111 11111111 11111110
//补码:11111111 11111111 11111111 11111111
// ~a: 00000000 00000000 00000000 00000000
//~a 符号位是0 是正数,正数的原 反 补 相同
// ~a 原码 :00000000 00000000 00000000 00000000
// b=0;
return 0;
}
四、赋值操作符
= += -= /= %= *= &= |= ^=
用于为创建的变量全局变量赋值
int main()
{
int num = 0;
// +=
num = num + 10;
num += 10;
//这两种写法是一致的,没有本质的区别
//其余的操作符都是大同小异的
return 0;
}
五、单目操作符
! :逻辑取反
- :负值
+ :正值
& :取地址
sizeof 操作符
~ :对一个二进制按位取反
-- :自减
++ :自加
* :解引用
类型):强制类型转换
1、&(取地址)
我们通过 & (取地址操作符)取出一个变量的内存地址,把地址存放到一个变量里面,那这个变量就是指针变量
int main()
{
int num = 1;
//通过 & 操作符取出变量的地址存放到指针变量中
int* pi = #
//pi就是一个指针变量
return 0;
}
2、*(解引用)
* 与 & 是一对相对的操作符,我们通过 *(解引用操作符)可以对一个指针变量进行打印与赋值
int main()
{
int num = 1;
//通过 & 操作符取出变量的地址存放到指针变量中
int* pi = #
//pi就是一个指针变量
//通过 *(解引用操作符)可以对一个指针变量进行打印与赋值
printf("%d\n", *pi);
*pi = 10;
printf("%d\n", *pi);
return 0;
}
3、++和--
++ --
不管是前置++,还是后置++,都会使得操作数加1
后置++,先使用,后++
前置++,先++,后使用
int main()
{
int a = 1;
// 不管是前置++,还是后置++,都会使得a加1
a++;
printf("%d\n", a);
++a;
printf("%d\n", a);
int b = a++;// 后置++,先使用,后++
printf("%d\n", a);//2
printf("%d\n", b);//1
int b = ++a;// 前置++,先++,后使用
printf("%d\n", a);//2
printf("%d\n", b);//2
}
4、(类型)强制类型转换
(类型)
int main()
{
int a = 1.1;// 编译器会报警告,此时就可以使用强制类型转换
double b = 99 / 8;// 此时除号两边会采用整数的运算方式,得到的是商
double c = 99 / (double)8;// 此时除号两边会采用浮点数的运算方式
printf("%d\n", a);
printf("%lf\n", b);
printf("%lf\n", c);
//我们使⽤强制类型转换都是万不得已的时候使⽤,如果不需要强制类型转化就能实现代码,这样⾃然更好的
return 0;
}
六、逻辑操作符
&&--逻辑与 ||--逻辑或 !--逻辑非
逻辑操作符用于 if 语句中的条件判断
1、&&
&& 操作符两边的操作数必须同时为真时,整个表达式才为真
int main()
{
bool con1 = true;
bool con2 = false;
//&& 操作符两边的操作数必须同时为真时,整个表达式才为真
if (con1 && con2)
{
printf("true\n");
}
else
{
printf("false\n");
}
//false
return 0;
}
2、||
|| 操作符两边的操作数其中一个为真时,整个表达式才为真
int main()
{
bool con1 = true;
bool con2 = false;
//|| 操作符两边的操作数其中一个为真时,整个表达式才为真
if (con1 || con2)
{
printf("true\n");
}
else
{
printf("false\n");
}
//true
return 0;
}
3、!
! 操作符的操作数逻辑取反,即真为假,假为真
int main()
{
bool con1 = true;
bool con2 = false;
//! 操作符的操作数逻辑取反,即真为假,假为真
if (!con1)
{
printf("true\n");
}
else
{
printf("false\n");
}
// false
return 0;
}
七、条件操作符
表达式1 ?表示式2 :表达式3 ;
条件操作符,又叫三目运算符,因为有三个操作数
当表达式1 为真执行表达式2 ,否则执行表达式3
#include <stdio.h>
int main()
{
//输入两个数打印两个数中的较大值
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int max = (a > b ? a : b);
printf("%d\n", max);
// 0
//a > b ? printf("%d\n", a) : printf("%d\n", b);
return 0;
}
八、逗号表达式
表达式1,表达式2,……
逗号表达式就是用逗号隔开多个表达式
逗号表达式从左向右依次执行
逗号表达式的结果就是最后一个表达式
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
int c = 30;
//d的结果就是逗号表达式中最后一个表达式的结果
//也就是将c的值赋给d
int d = (a, b, c);
printf("%d\n", d); // d为30
}
九、[ ] 下标引用 与( ) 函数调用
1、[ ] 下标引用
、 用于访问数组的元素
arr[ i ] 等价于 *(arr+i)
int main()
{
// [ ] 下标引用
int len = 10;
int arr[len];
for (int i = 0; i < len; i++)
{
arr[i] = i;
printf("%d ", arr[i]);
//arr[ i ] 等价于 *(arr+i)
printf("%d ",*(arr+i);
}
//0 1 2 3 4 5 6 7 8 9
return 0;
}
2、( ) 函数调用
函数名():进行函数调用
()里面可以有参数,也可以没有参数
函数调用操作符,至少有一个操作数,函数名也是它的操作数,其余操作数就是所传的参数
// 定义函数
void print(int num, int n)
{
printf("%d %d\n", num, n);
}
int main()
{
printf("%d\n", 123456);// ( ) 函数调用
print(123456, 789);// ( ) 函数调用
// 123456 789
return 0;
}
十、结构体成员访问操作符
. ->
1、.
结构体变量 . 成员变量
用结构体变量访问结构体成员
#include <stdio.h>
//创建结构体
struct SS
{
char name[10];
int age;
};
int main()
{
//创建结构体变量并初始化
struct SS s1 = { "张三",18 };
struct SS s2 = { .age = 19,.name = "李四" };
//访问结构体成员(结构体变量 . 成员变量)
printf("名字:%s 年龄:%d\n", s1.name, s1.age);
printf("名字:%s 年龄:%d\n", s2.name, s2.age);
}
2、->
结构体指针->结构体成员变量
用结构体指针访问成员
【注意】
此操作符只能用于结构体指针变量
#include <stdio.h>
//创建结构体
struct SS
{
char name[10];
int age;
};
int main()
{
//创建结构体变量并初始化
struct SS s1 = { "张三",18 };
//创建结构体指针变量 让其指向s1
struct SS* p = &s1;
// 用结构体指针访问成员(->)
printf("名字:%s 年龄:%d\n", p->name, p->age);
}