一、二进制和进制转换
1. 2进制直接转8进制

2. 2进制直接转16进制

二、原码、补码、反码
整数的2进制表示方法有3种:原码、反码、补码
有符号整数的三种表示方法均有符号位和数值位两种,2进制序列中,最高位是符号位,其余是数值位。
无符号整数和正整数没区别
正整数的原码、反码、补码均相同
负整数的三种表示方式均不相同

对于整形来说,数据存放内存中其实存放的是补码
在计算机系统中,数值统一用补码来表示和储存。因为使用补码可以将数值域统一处理,并且原码补码相互转换,运算的过程是相同的


三、移位操作符
1.左移操作符 <<

一定是用-10的2进制补码来移位计算!!
2.右移操作符 >>
1. 逻辑右移:左边⽤0填充,右边丢弃2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
到底用哪种取决于编译器 但大部分编译器都是算术右移
相当于/2!!

a << -1 //error
四、位操作符
& 按位与
有0则0,无0则1

| 按位或
有1则1,无1则0

^ 按位异或
同则0,异则1

规则:
x ^ x = 0
x ^ 0 = x
x 是任何整数
~ 按位取反
将操作数的每一位二进制位都取反

练习
1.不能创建临时变量,实现两个整数的交换
int main()
{
int x = 10;
int y = 20;
printf("%d %d\n", x, y);
x = x ^ y;
y = x ^ y;
x = x ^ y;
printf("%d %d\n", x, y);
return 0;
}
2.求⼀个整数存储在内存中的⼆进制中1的个数
方法一:用 n & 1,得到最右边一位的数,遍历32位

方法二:用 n = n & (n-1) 来去掉n最右边的1

3.⼆进制位置0或者置1 ,编写代码将13⼆进制序列的第5位修改为1,然后再改回0
int main()
{
int a = 13;
// 000000001101
// 第5位改成1
// | 000000010000 (1 << 4)
// 000000011101
int a1 = a | (1 << 4);
//再改回来 ~(1<<4)
// 111111101111
// a1 & ~(1<<4)
// 000000001101
int a2 = a1 & ~(1 << 4);
return 0;
}
五、单目操作符
!、++、--、+、-、&、*、~、sizeof、(类型)
单目操作符的特点是只有一个操作数
+、-:这里表示负数和正数。如-5,+3
(类型):表示强制类型转换。如 int a =10;
double b = (double)a;
六、逗号表达式
exp1, exp2, exp3, …expN

if语句里也可能出现逗号表达式:
if (d = a + 1, c = a / 2, d > 0)
依次算前面的表达式,但只有最后一个决定if语句
for循环里也可能出现,比如要用两个变量控制
for (a = 1, b = 2; a < 5 && b < 8; a += 1, b += 2)
一个逗号表达式 又一个逗号表达式
逗号表达式还可以简化代码
a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
//...
a = get_val();
count_val(a);
}
如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
//业务处理
}
七、下标访问[]、函数调用()
1.[ ]下标引用操作符
操作数:一个索引值 + 一个数组名
2.函数调用操作符
操作数:函数名 + 传递给函数的参数个数
八、结构成员访问操作符
结构体成员的直接访问
结构体成员的直接访问是 . 操作符访问的
. 的前面和后面是它的操作数,两个操作数
结构体成员的间接访问
有时候我们没有创建一个该结构体类型的变量,而是一个指向该结构体的指针

九、操作符的属性:优先级、结合性
这两个属性决定了表达式求值的运算顺序
优先性
看相邻的不同运算符先算哪一个
结合性
若两个运算符优先性相同,看结合性,根据运算符是左结合还是右结合来确定执行顺序。大多数运算符是左结合(从左向右执行)

十、表达式求值
整型提升
C语言中计算总是至少以默认整型类型的精度来运行
有符号整数提升是按照变量的数据类型的符号位来提升的无符号整数提升,⾼位补0

算术转换
long double ^double |float |unsigned long int 只能向上转换long intunsigned intint
不创建临时变量交换两个变量


1059

被折叠的 条评论
为什么被折叠?



