+ |
加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余(操作数必须为整数) |
算数转换:
char -> int -> float -> double
数据存储:二进制补码
<< | 左移(左边抛弃,右边补零) |
>> | 右移 (1.逻辑移位:左边补零,右边抛弃 2.算数移位:左边补符号位,右边抛弃) |
循环移位:
超过32位,对32位取模
>>33 -> >>1
不能移动负数位,此行为标准未定义!(编译器中)
负数位绝对值加移动实际值=32
>>-1 -> >>31
>>-5 -> >>27
void shift(int ls,int rs)
{
printf("左移——%d\n", ls << 1);
printf("左移未赋值——%d\n", ls);
ls = ls << 1;
printf("左移后赋值——%d\n", ls);
printf("右移后——%d\n", rs >> 1);
printf("右移未赋值——%d\n", rs);
rs = rs >> 1;
printf("右移后赋值——%d\n", rs);
}
操作数必须为整数
& | 按位与(同为1则为1) |
| | 按位或(同为0则为0) |
^ | 按位异或(相同为0,不同为1) |
void Anoperator(int a, int b) // a--1 b--2
{
printf("按位与——%d\n", a & b); //0
printf("按位或——%d\n", a | b); //3
printf("按位异或——%d\n", a ^ b); //3
}
不能创建临时变量(第三个变量),实现两个数的交换。
//不能创建临时变量(第三个变量),实现两个数的交换。
//改变实参可用传址调用,此函数为传值
void swap(int a, int b)
{
printf("a = %d b = %d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d b = %d\n", a, b);
}
计算数字二进制中一的个数
int count_One(int n) //计算数字二进制中一的个数
int count;
while(n)
{
n&=(n-1);
count++;
}
return count;
}
= | 赋值 |
+= | 加等 |
-= | 减等 |
*= | 乘等 |
/= | 除等 |
%= | 取余等 |
>>= | 右移等 |
<<= | 左移等 |
&= | 按位与等 |
|= | 按位或等 |
^= | 按位异或等 |
int x=2;
//等价
x+=10;
x=x+10;
! | 逻辑反 |
- | 负值 |
+ | 正值 |
& | 取地址 |
sizeof | 操作数的类型长度(字节为单位,返回无符号整型) |
~ | 对一个数的二进制按位取反 |
-- | 前置,后置-- |
++ | 前置,后置++ |
* | 简介访问操作符(引用操作符) |
(类型) | 强制类型转换 |
++,--
前置 | 操作数先自增(减),后使用 |
后置 | 操作数先使用,后自增(减) |
~ 按位取反
-10,按位取反 值为-11
负数在计算机中以补码存储。
-10的原码: 10000000 00000000 00000000 00001010
取反后 : 11111111 11111111 11111111 11110101 符号位不变、其位取反
计算机认为为补码,打印时将其返还为原码(负数的补码:原码->反码+1=补码)
打印值 : 10000000 00000000 00000000 00001011
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
!= | 不等 |
== | 相等 |
注:
==为相等测试
=为赋值
&& | 逻辑与 |
|| | 逻辑或 |
短路表达:
&&:左边为false时,右边不执行
||:左边为true时,右边不执行
#include
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
//i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
i = a++||++b||d++;
exp1? exp2:exp3 | exp1为真,执行exp2,否则exp3 |
int max(int a, int b) // a--1 b--2
{
return a > b ? a : b;
}
exp1, exp2, exp3, …expN
逗号隔开多个表达式,从左到右依次执行,整个表达式结果为最后一个表达式的值。
进行多个操作符运算时,活用()来确定运算顺序,避免在不同编译器中结果不同!
数组名+下标
(数组篇:数组篇)
函数名+参数
(函数篇:函数篇)
结构体.成员名
结构体指针->成员名
C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型 提升。
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。 通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。
所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
//负数的整形提升,符号位不变,高位补一;
char c1 = -1;
变量c1的二进制位(补码)中只有8个比特位: 1 1111111
提升之后的结果是: 1 1111111 11111111 11111111 11111111
//正数的整形提升
char c2 = 1;
变量c2的二进制位(补码)中只有8个比特位: 00000001
提升之后的结果是: 0 0000000 00000000 00000000 00000001
//无符号整形提升,高位补0
void intImprove()
{
char a = 182;//(Oxb6200) 超出char表数范围 整型提升后为负数;
short b = 46592;
int c = 10000000;
if (a == 100)
printf("a\n");
if (b == 46592)
printf("b\n");
if (c == 10000000)
printf("c\n");
}
c
void intImprove2()
{
char c = 10;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(!c));
printf("%u\n", sizeof(c));
}
1
4
1
1
c 只要参加表达式运算,就整型提升。
操作符所操作的操作数类型不同,低类型转高类型;
转换要合理
高类型转低类型时,会发生精度丢失
float f=1.23;
int i=f; //i=1;
最难不过坚持!