+ — * / %
注意:取模运算是整数间的运算!
#2 移位操作符<< // 左移操作符 >> // 右移操作符
将对应二进制左移n位,也即乘2^(n)。
右移有两种:算术右移(右边丢弃,左边补原符号位)、逻辑右移(右边丢弃,左边补0)
#3 位操作符& // 按位与 | // 按位或 ^ // 按位异或
&的一个应用场景:
// 计算一个数的二进制中1的个数的两种实现方法
int Function_1(int num)
{
int digits = 0;
int i = 0;
int count = 0;
digits = sizeof(num) * 8;
for (i = 0; i < digits; i++)
{
if ((num >> i) & 1 == 1) // 将num与1相与后,如果该位是1,则返回1;如果该位是0,则返回0;然后左移1位,依次计算
count++;
}
return count;
}
int Function_2(int num) // 原理不是很清楚
{
int count = 0;
while (num)
{
num = num & (num - 1);
count++;
}
return count;
}
a^a = 0; 0^a=a
异或运算的一个应用场景:
// 交换两个数,不能用第三个变量
int a = 3;
int b = 5;
printf("a=%d, b=%d", a, b); // a=3, b=5
a = a ^ b;
b = a ^ b; // 相当于a^b^b=a^(b^b)=a^0=a
a = a ^ b; // 相当于a^b^a=a^a^b=0^b=b
printf("a=%d, b=%d", a, b); // a=5, b=3
#4 赋值操作符
= += -= /= *= %= >>= <<= &= |= ^=#5 单目操作符
! // 逻辑反 - // 负号 + // 正号 & sizeof // 操作数的类型长度(单位:字节) ~ // 对一个数的二进制按位取反 -- ++ * // 间接访问操作符(解引用操作符) (类型) // 强制类型转换
// 对于sizeof有一个特殊写法
int arr[10] = { 0 };
printf("%dn", sizeof(int [10]));
注意:sizeof()括号中的表达式是不参与运算的!如下图所示:
#6 关系操作符> // 大于 < // 小于 >= // 大于等于 <= // 小于等于 != // 不等于 == // 等于
比较两个字符串不能用==
#7 逻辑操作符&& // 逻辑与 || // 逻辑或
注意:
逻辑或,如果左边确定为真,就直接返回真,右边的表达式就不会去执行了。
逻辑与,如果左边确定为假,就直接返回假,右边的表达式就不会去执行了。
#8 条件操作符(三目操作符)表达式1 ? 表达式2 : 表达式3
当表达式1为真时,执行表达式2;当表达式1为假,执行表达式3。
#9 逗号操作符表达式1 , 表达式2, 表达式3, 表达式4; ...; 表达式N
从左向右依次计算,整个表达式的结果是最后一个表达式的结果。
例子:
if(a = b + 1, c = a / 2, d > 0)
上面三个表达式从左向右依次算,但决定if()括号内是真是假的只有d>0这个表达式。
使用逗号运算符还可以简化代码:
a = get_val();
count_val(a);
while (a > 0)
{
// 要执行的代码
a = get_val();
count_val (a);
}
// 如果使用逗号表达式,改写:
while (a = get_val(), count_val(a), a > 0)
{
// 要执行的代码
}
#10 下标引用、函数调用、结构成员
1. [] // 下标引用符 2. () // 函数调用操作符 3. . -> // 结构成员操作符
前两个没什么好讲的,主要说一下最后一个。
结构体例子:
// 结构体定义
struct Book
{
char name[20];
char id[20];
int price;
};
int main()
{
struct Book b = {"C语言", "c20220718", 88};
printf("书名:%sn", b.name);
printf("书号:%sn", b.id);
printf("定价:%dn", b.price);
// 也可以这样访问
struct Book * pb = &b;
printf("书名:%sn", (*pb).name);
printf("书号:%sn", (*pb).id);
printf("定价:%dn", (*pb).price);
// 也可以这样子
struct Book * pb = &b;
printf("书名:%sn", pb->name);
printf("书号:%sn", pb->id);
printf("定价:%dn", pb->price);
return 0;
}
. 操作符用于获取结构体里的成员,(结构体变量名.成员名)
-> 操作符(结构体指针->成员名)
#11 表达式求值表达式求值顺序有操作符的优先级和结合性决定,同时有些操作符在求值过程中可能需要转换为其他类型。
整型提升:表达式中的字符和短整型操作数(小于int长度的整型值)在使用前被转换为普通整型。按照变量的数据类型的符号位来提升。
int main()
{
char a = 0xb6;
short b = 0xb600;
int c= 0xb6000000;
if (a==0xb6)
printf ("a");
if (b==0xb600)
printf ("b");
if (c==0xb6000000)
printf ("c");
return 0;
}
结果只有C,因为a和b都整型提升了!
算数转换:某个操作符的各个操作数属于不同类型,需要统一类型。
转换顺序为:int -> unsigned int -> long int -> unsigned long int -> float -> double -> long double
操作符属性:复杂表达式求值有三个影响因素:①操作符优先级 ②操作符结合性 ③是否控制求值顺序



