C语言操作符详解(上)

1.操作符的分类

  • 算术操作符:+、-、*、/、%
  • 移位操作符:<<   >>   (移动的是二进制位
  • 位操作符:&  |  ^  (也是使用二进制位进行计算
  • 赋值操作符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=
  • 单目操作符:!、++、--、&、*、+、-、~、sizeof、(类型)
  • 关系操作符:>、>=、<、<=、==、!=
  • 逻辑操作符:&&、||
  • 条件操作符:? :
  • 逗号表达式:,
  • 下标引用:[ ]
  • 函数调用:()
  • 结构成员访问:. 、->

2.原码、反码、补码

整数的二进制表示方法有3种

有符号整数的三种表示方法均有符号位和数值位两部分,二进制序列中,最高位的一位当作符号位,其余都是数值位。符号位中:0表示正,1表示负

正整数的原、反、补码都相同

负整数的三种表示方法各不相同

原码:直接将数值按照正负数的形式翻成二进制

反码:将原码的符号位不变,其他位依次按位取反

补码:反码+1

补码原码相互转化:取反+1

int b=10;
//0000000000000000000000000001010--原码
//0000000000000000000000000001010--反码
//0000000000000000000000000001010--补码

int a=-10;
//1000000000000000000000000001010--原码
//1111111111111111111111111110101--反码
//1111111111111111111111111110110--补码

对于整数来说:整数在内存中存放的就是其二进制的补码

why?在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程都是相同的,不需要额外硬件电路。

3.移位操作符

<<左移位操作符

>>右移位操作符      注:移位操作符的操作数只能是整数

3.1左移操作符 <<

左边舍弃,右边补0

  • 左移一位有乘二的效果哦
int a=10;
int b=a<<1;//a左移一位--->移动的是二进制位

//10的二进制1010,a占4个字节
//00000000000000000000000000001010
//00000000000000000000000000010100

printf("b=%d\n",b);//20
printf("a=%d\n",a);//10

//若相让a变化,则写a <<= 1

注意:存储形式是补码,要先转化为补码形式再左移,还要换成原码,显示出来的是原码十进制 

int a = -1;
int b = a << 1;

//100000000000000000000000000000001--a的原码
//111111111111111111111111111111110
//111111111111111111111111111111111--补码
//左移一位
//111111111111111111111111111111110--b的补码
//100000000000000000000000000000001
//100000000000000000000000000000010--b的原码

printf("b=%d\n",b);//-2
printf("a=%d\n",a);//-1

3.2右移操作符 >>

  1. 逻辑右移:左边补0,右边舍弃
  2. 算术右移:左边该值的符号位填充,右边舍弃

右移到底采用哪种方式取决于编译器,通常采用算术右移。有除二的效果

int a = -10;
//1000000000000000000001010--a原码
//1111111111111111111110101
//1111111111111111111110110--补码

int b = a >> 1;//算术右移
//1111111111111111111111011--b补码
//1000000000000000000000100
//1000000000000000000000101--b原码

printf("b=%d\n",b);//-5
printf("a=%d\n",a);//-10

4.位操作符:&、|、^、~

  1. &     //按(二进制)位与       有0为0,同为1则1
  2. |       //按(二进制)位或       只要有1则为1,同时为0才0
  3. ^      //按(二进制)位异或    相同为0,相异为1
  4. ~      //按(二进制)位取反    取反得到补码    

注意:他们的操作数必须是整数

int a = 6;
//0000000000000000000000000000000110---6的补码(正数原反补相同)
//
int b = -7;
//1000000000000000000000000000000111
//1111111111111111111111111111111000
//1111111111111111111111111111111001--->-7的补码

int c = a & b;//a和b的补码的二进制位进行运算
//对于二进制位补码,有0则为0,两个同时为1,才为1
//0000000000000000000000000000000110---> 6的补码
//1111111111111111111111111111111001--->-7的补码
//0000000000000000000000000000000000
//c = 0


int c = a | b;//规则:只要有1,就是1,两个同时为0,才为0
//0000000000000000000000000000000110---> 6的补码
//1111111111111111111111111111111001--->-7的补码
//1111111111111111111111111111111111--->c的补码
//1000000000000000000000000000000001--->c的原码
//c = -1 


int c = a ^ b;//按位异或:相同为0,相异为1
//0000000000000000000000000000000110---> 6的补码
//1111111111111111111111111111111001--->-7的补码
//1111111111111111111111111111111111
//1000000000000000000000000000000001--->原码
//c = -1
int a = 0;
printf("%d",~a);
//~ 按位取反
//00000000000000000000000000000000 -- 0的补码
//11111111111111111111111111111111 -- 取反 (~a补码)
//00000000000000000000000000000001 -- 原码
~a = -1

4.1操作符的特点

 ^ 支持交换律

3 ^ 5 ^ 3 = 5

3 ^ 3 ^ 5 = 5 

//不能创建第三个变量实现两数交换
int main()
{
    int a = 3;
    int b = 5;
   
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;  //a^a^b=b
}
//实现交换
0 ^ a = a
a ^ a = 0

4.2练习题

练习1:求一个整数存储在内存中的二进制的1的个数

#include<stdio.h>

int count_bit_1(unsigned int n)
{
    int count=0;
    while(n)  //把n转化为二进制,求其中1的个数,除基取余
    {
        if((n%2) == 1)
           count ++;
       
        n = n / 2;//得到商
     }
    return count;
}

int main()
{
     int num=0;
     scanf("%d",&num);
     int ret = count_bit_1(num);//传入无符号整型
     printf("%d\n",ret);
}


//方法二
int count_bit_1(int n)
{
   
    int count=0;
    for(int i=0;i<32;i++)
    {
        if(((n>>i) & 1) == 1)
         {
           count ++;
          }
     }
     return count;
}
缺点:会把每一位都算一遍


//方法三

int count_bit_1(int n)
{
    int i= 0;
    int count=0;
    while(n)         //有几个1循环几次
    {
        n=n&(n-1);
        count ++;
     }
     return count;
}

n & 1 == 1   //说明n最后一位是1

n-1    //把n的二进制序列中的最右边的1去掉了

n = n & (n-1)  逐次去掉一个1

【例】n  = 1011

        n-1  = 1010

            n = 1010

         n-1 = 1001

            n = 1000

练习2:判断n是否是2的次方数

思路:2的次方数的二进制数中只有一个1

if(n&(n-1) == 0)
{
    cout<<"yes";
}

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值