69 操作符详解
算数操作符
+ - * / %
- 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
- 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法
- % 操作符的两个操作数必须为整数。返回的是整除之后的余数
移位操作符(二进制位)
- 不能移动负数位,例如10>>-1 //error
>>右移操作符
1.算数右移(基本上都是)
右边丢弃,左边补原符号位
2.逻辑右移
右边丢弃,左边补0
<<左移操作符
左边丢弃,右边补0
位操作符
& 按位(2进制位)与
| 按位或
^ 按位异或:形同为0,相异为1
(操作数必须为整数)
//不创建临时变量,实现两个数的交换
//加减法
a=a+b;//缺陷:可能会溢出
b=a-b;
a=a-b;
- 异或的结果和原来其中一个值异或能得到另外一个值
- a^a=0; 0^a=a;
int main()
{
int a = 10;
int b = 20;
printf("before:a=%d b=%d\n", a, b);
//异或法
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("after:a=%d b=%d\n", a, b);
return 0;
}
//求一个整数存储在内存中的二进制数中1的个数
while (num)
{
if (num % 2 == 1)
count++;
num = num / 2;
}
方法2 :
for (i = 0; i < 32; i++)
{
if(1==(num>>i)&i)
count++:
}
赋值操作符
单目操作符
只有一个操作数
- ! 逻辑反操作
- - 负值
- + 正值
- & 取地址
- sizeof()操作数的类型长度,以字节为单位
- ~ 按位取反(包括符号位)
- -- ++ 前置 (先++ --再使用)
- 后置 -- ++ (先使用再++ --)
- * 间接访问操作符(解引用操作符)
- (类型) 强制类型转换
sizeof(表达式):sizeof()里面的表达式不参与运算
关系操作符
> >= < <= != ==
=赋值 == 判断相等
比较两个字符串相等时,不能使用==
逻辑操作符
&& 逻辑与 如果左边算出来是假,右边不会进行运算
|| 逻辑或 如果左边算出来是真,右边不会进行运算
条件操作符
(三目操作符)
condition ? consequent : alternative
condition
表达式的计算结果必须为 true
或 false
。 若 condition
的计算结果为 true
,将计算 consequent
,其结果成为运算结果。 若 condition
的计算结果为 false
,将算 alternative
,其结果成为运算结果。 只会计算 consequent
或 alternative
。
逗号表达式
逗号表达式:从左向右依次执行,整个表达式的结果是最后一个表达式的结果
下标引用、函数调用和结构成员
[ ] 下标引用操作符
操作数:一个数组名+一个索引值
( ) 函数调用操作符,接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数
访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
//创建了一个自定义的类型
struct Book
{
//结构体的成员(变量)
char name[20];
char id[20];
int price;
};
int main()
{
//结构体变量名.成员名
struct Book b = {"C语言", "C20210509", 55};
struct Book * pb = &b;
//结构体指针->成员名
printf("书名:%s\n", pb->name);
printf("书号:%s\n", pb->id);
printf("定价:%d\n", pb->price);
printf("书名:%s\n", (*pb).name);
printf("书号:%s\n", (*pb).id);
printf("定价:%d\n", (*pb).price);
printf("书名:%s\n", b.name);
printf("书号:%s\n", b.id);
printf("定价:%d\n", b.price);
return 0;
}
74 表达式求值
隐式类型转换
整型提升:在表达式计算时,各种整形首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型;然后执行表达式的运算。
C语言标准中仅规定了:
char的长度 ≤ short int的长度 ≤ int的长度
这意味着short int与int的长度相等的可能。这种情形下,unsigned short就无法提升为int表示,只能提升为unsigned int。
整形提升是按照变量的符号位来提升的。无符号整形提升,高位补0。
int main()
{
//发现a和b都是char类型的,都没有达到一个int的大小
//这里就会发生整形提升
char a = 3;
//00000000000000000000000000000011
//00000011 -char a
char b = 127;
//00000000000000000000000001111111
//01111111 - char b
char c = a + b;
//00000000000000000000000000000011 a整形提升后
//00000000000000000000000001111111 b整形提升后
//00000000000000000000000010000010 c
//10000010 - c只能放入8位
//打印的是%d,发生整形提升,高位是1,补1
//11111111111111111111111110000010 - 补码 提升后
//11111111111111111111111110000001 - 反码
//10000000000000000000000001111110 - 原码
//-126
printf("%d\n", c); //-126
return 0;
}
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
0xb6——1011 0110
编译器把char定义为signed char(C语言标准没有规定char类型是有符号还是无符号);表达式a==0xb6被整型提升,其中char类型的a提升为int类型并为一个负值,因此这个表达式的结果为false;表达式b==0xb600被整型提升,其中short类型的b提升为int类型并为一个负值,因此这个表达式的结果为false;表达式c == 0xb6000000没有做整型提升,==运算符的两段都是int类型的负值,其结果为true。
int main()
{
char c = 1;
printf("%u\n", sizeof(c));//1 char
printf("%u\n", sizeof(+c));//4 unsigned int
printf("%u\n", sizeof(-c));//4 unsigned int
printf("%u\n", sizeof(!c));//4 gcc 编译为 4 unsigned int
return 0;
}
c只要参与表达式运算,就会发生整形提升
算术转换
94 算数转换作业讲解
//计算参数n的二进制补码中有几个1
//存在一定的问题:只能求正数
int NumberOf1(int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
int NumberOf1(int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
count++;
}
}
return count;
}
每次n&(n-1) 都去掉二进制数中的一个1
int NumberOf1(int n)
{
int count = 0;
int i = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
//写一个代码判断一个数字是不是2的n次方
因为2的n次方的数字,其中只有一个1。只需判断下(k&(k-1) == 0),等于0就是2的n次方。
//二进制不同位的个数
for (i = 0; i < 32; i++)
{
if (((m >> i) & 1) != ((n >> i) & 1))
{
count++;
}
}
//另一种方法
int ret = m ^ n;//相同为0,相异为1
count = NumberOf1(ret);//统计下异或后的结果中有几个1,就说明m和n的二进制位中有几个不同
printf("%d\n", count);
//打印整数二进制的奇数位和偶数位
int i = 0;
//打印偶数位
for (i = 31; i >= 1; i -= 2)
{
printf("%d ", (n >> i) & 1);
}
printf("\n");
//打印奇数位
for (i = 30; i >= 0; i -= 2)
{
printf("%d ", (n >> i) & 1);
}