C语言学习--操作符

算数操作符

算数操作符包括,四则操作符 + - * / 和 取模操作符 %

+ - * 的运算规则与数学中相同,重点介绍 /%的注意点。

  1. /号两边得操作数如果都是整数,执行的是整数除法,结果为整数商,余数被舍弃。
int main()
{
   
    // 两边为整数
    int a = 5 / 2;     // == 2
    // 有一个浮点数
    float f = 5 / 2.0; // == 2.500000  结果默认小数点后六位     
    return 0;
}
  1. % 号两边的操作数必须都是整数,结果为整除后的余数
int main()
{
   
    // 两边为整数
    int a = 5 % 2;     // == 2
    // 有一个浮点数
    int b = 5 % 2.0;   // 非法,左右操作数必须为整型
    float f = 5 % 2.0; // 非法
    return 0;
}
  1. 除了 % 其他的算数操作符都可以作用于整数和浮点数。

移位操作符

移位操作符包括,右移操作符>>和左移操作符<<

移位操作符移动的是数二进制位,移位操作符只能作用与整数

二进制数

我们通常是使用10进制来表示一个数,例如1234,千位1,百位2,十位3,个位4,个位的权重为100,十位为101,百位为102,千位为103

用每一位上的数 × 权重,再相加就能得到这个10进制数。
1234 = 1 × 1 0 3 + 2 × 1 0 2 + 3 × 1 0 1 + 4 × 1 0 0 1234 = 1 \times 10^3 + 2 \times 10^2 + 3 \times 10^1 + 4 \times 10^0 1234=1×103+2×102+3×101+4×100
而计算中在存储数据是以二进制数来存储,二进制数只有1,0二种表示方式,逢2进1。例如二进制数0111,它的第0位的权重是20,第1位的权重是21,第二位的权重是22

用每一位的数 × 权重,再相加就能得到这个2进制数的十进制表示。
7 = 1 × 2 2 + 1 × 2 1 + 1 × 2 0 7 = 1 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 7=1×22+1×21+1×20

原码、反码、补码

计算机中用二进制数的最高位来表示正负,也称为符号位,0表示正数,1表示负数,剩余的位用来表示二进制数的绝对值。

有符号位数的二进制表示有:原码、反码、补码。

原码

最高位表示数的符号,其他位表示数值

7 == 00000111

-7 == 10000111

反码

  1. 正数的反码和原码相同

    7 == 00000111 == 7

  2. 负数的反码等于原码符号位不变,其他位按位取反。

    -7 == 10000111 <==> 11111000 == -7

补码

  1. 正数的补码、反码、原码相同

    7 == 7 == 7 == 00000111

  2. 负数的补码等于反码 + 1

    -7 == 10000111 <=> 11111000 = -7 <=> 11111001 = -7

计算机在存储数据时中存储的是二进制的补码,使用补码的方式存储是因为可以用加法同时处理加法与减法运算。

例如: 1 - 1 = 1 + (-1) = 0

  1. 用原码方式相加

    1 = 00000001,-1 = 10000001

    00000001 + 10000001 = 10000002 = -2 (错误)

  2. 用反码方式相加

    1 = 00000001,-1 = 11111110

    00000001 + 11111110 = 11111111 = 10000000 = -0

    -0 虽然和 0 相同,但是用2个组合来表示一个数有些浪费,因此不可取。

  3. 用补码方式相加

    1 = 00000001,-1 = 11111111

    00000001 + 11111111 = 100000000 = 0 (正确)

    经过计算,1会进到第8位,多出的最高位溢出被舍弃,0则变为符号位,因此得出的结果为正数,他的原反补相同。

右移操作符 >>

因为计算机中存储的是补码,所以在移位操作时,操作的也是补码的位。

右移操作又分为:

  1. 算数右移

    右边舍弃,左边补原符号位

  2. 逻辑右移

    右边丢弃,左边补0

    VS中为算数右移

// 正数原反补相同
int main()
{
   
	int a = 16;
	int b = a >> 1; // 右移操作符,将16的二进制位向右移动一位
	//16 == 00000000000000000000000000010000 >> 1
	// b == 00000000000000000000000000001000 == 8
	int c = a >> 2;
	//16 == 00000000000000000000000000010000 >> 2
	// c == 00000000000000000000000000000100 == 4
	printf("%d\n", b);  // 8
	printf("%d\n", c);  // 4
    // 右移一位相当于 十进制数 / 2;
}
// 负数
int main()
{
   
    int a = -16;
    int b = a >> 1; 
    // -16原码 == 1000 0000 0000 0000 0000 0000 0001 0000 
    // -16反码 == 1111 1111 1111 1111 1111 1111 1110 1111 
    // -16补码 == 1111 1111 1111 1111 1111 1111 1111 0000 >> 1
    // b的补码 == 1111 1111 1111 1111 1111 1111 1111 1000 
    // b的反码 == 1111 1111 1111 1111 1111 1111 1111 0111 
    // b的原码 == 1000 0000 0000 0000 0000 0000 0000 1000 == -8
     printf("b = %d\n", b);
    
    int c = a >> 5;
    // -16补码 == 1111 1111 1111 1111 1111 1111 1111 0000 >> 5
    // c的补码 == 1111 1111 1111 1111 1111 1111 1111 1111 
    // c的反码 == 1111 1111 1111 1111 1111 1111 1111 1110
    // c的原码 == 1000 0000 0000 0000 0000 0000 0000 0001 == -1
    printf("%d\n",c);
    return 0;
    
    // c的结果可以看出,负数右移时最大为-1,因为每次补的都是1,最终补码的值是全1,而全1转换为原码就是-1
}

在这里插入图片描述

左移操作符 <<

左移操作的规则只有:左边丢弃,右边补0

// 正数
int main()
{
   
	int a = 16;
	int b = 16 << 1;
    // a == 0000 0000 0000 0000 0000 0000 0001 0000 << 1
    // b == 0000 0000 0000 0000 0000 0000 0010 0000 == 32
    printf("b = %d\n", b);
    
    // 左移操作符在移动时可能会改变符号
    short c = 16385; // 0100 0000 0000 0001
    short d = c << 1;
    // c的补码 == 0100 0000 0000 0001 << 1
    // d的补码 == 1000 0000 0000 0010 得到负数
    // d的反码 == 1000 0000 0000 0001 
    // d的原码 == 1111 1111 1111 1110 == -32766
      printf("d = %d\n",d)
          
    short e = -1; 
    short f = e << 1;
    // e的原码 == 1000 0000 0000 0001 
    // e的反码 == 1111 1111 1111 1110
    // e的补码 == 1111 1111 1111 1111 << 1
    // f的补码 == 1111 1111 1111 1110
    // f的反码 == 1111 1111 1111 1101
    // f的原码 == 1000 0000 0000 0010  == -2
    	

	return 0;
}

在这里插入图片描述

注意

移位操作符,不要移动负数位,这个标准是未定义的。

int a = 10;
int b = a >> -1; // 未定义,在VS2019中结果为0

位操作符

位操作符:按位与& 按位或| 按位异或^

位操作符,同样是操作补码得二进制位,并且只能操作整数

按位与&

同二进制位都为1时得1,其余情况得0

二进制数1 二进制数2 按位与&结果
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值