初识C语言之操作符详解(中)

一.复习

1.数值分为整数和小数,整数分为有符号整数和无符号整数。(有符号整数分为正数和负数)

2.原码取反为反码,反码+1为补码

二.操作符详解

1.移位操作符(参与运算的都是二进制数字的补码形式)

(1)   移位操作符分为左移操作符<<和右移操作符>>

(2)   规则:移位操作符类似于是对数字的二进制序列进行向左或者向右移动。其中被操作的对象数字必须为整数。

(3)   左移操作符的计算例子:

左移操作符运算规则为:将该数字二进制的补码序列左边丢弃n个数字,右边补n个0用作中和。

eg1.左移操作符

int a=10;    //因为int为4字节,则a为32bit位

int b=a<<3;//参与运算的是补码,因为10是正数则原码、反码、补码相同。

printf("%d",b);

10的二进制序列为:00000000000000000000000000001010

10<<3的二进制序列为:

00000000000000000000000001010000

a<<3的意思是将a的二进制序列左边三个数字丢弃,然后再将a的二进制序列后面补3个0,最后将此值赋给b,而后打印b的值。

eg2.左移操作符

int a=-1;//因为int为4个字节,所以a的二进制序列为32位,且最高位为符号位为1。

int b=a<<1;//参与运算的是存储在内存中的补码,所以需要先将a的补码写出来。

printf("%d",b);

-1的二进制原码:

10000000000000000000000000000001

-1的二进制反码:

11111111111111111111111111111110

-1的二进制补码:(参与运算的是二进制的补吗)

11111111111111111111111111111111

-1<<1二进制补码:(参与计算的是二进制的补码)

11111111111111111111111111111110

从而得出-1<<1的二进制原码:(补码取反后+1)

10000000000000000000000000000010

化成10进制后b为-2

(4)   左移操作符运算过程中左移1位有乘2的效果

(5)   右移操作符的不同种类

右移操作符的不同形式取决于编译器的不同。右移操作符分为逻辑右移和算数右移。其中主要为算数右移。逻辑右移的运算规则为将二进制的补码序列左边用n个0填充,右边丢弃n个数字。算数右移的运算规则为将二进制的补码序列左边用该数值的n个符号位的数字填充(原来为正数则填充0,原来为负数则填充1),右边丢弃n个数字用于中和。

(6)算数右移的例子

eg.

int a=-10;//因为int为4字节,所以a的二进制序列为32位,其中最高位符号位。

int b=a>>1;//参与运算时为a的二进制补码

printf("%d",b);

a的二进制序列原码:

10000000000000000000000000001010

a的二进制序列反码:

11111111111111111111111111110101

a的二进制序列补码:

11111111111111111111111111110110

b经过算数右移后的二进制序列补码:

11111111111111111111111111111011

b的二进制原码:(补码取反+1)

10000000000000000000000000000101

输出值b=-5

(7)   右移操作符的算数右移有÷2的效果


2.位操作符(只针对整数)

(1)   位操作符包括:按位与&,按位或|,按位异或∧,按位取反~。

(2)   位操作符的运算规则:

按位与&:有0则0,全1则1。

按位或|:有1则1,全0才0。

按位异或∧:相同则0,相异则1。

按位取反~:将该数字的二进制补码序列每一位取反。

(3)   位操作符的例子:

eg1.

int a = 6;

int b = 7;

int c = a&b;

a的二进制序列补码:

00000000000000000000000000000110

b的二进制序列补码:

11111111111111111111111111111001

c的二进制序列补码:

00000000000000000000000000000000

因为c的二进制序列补码的最高符号位为0,则c为正数,原码、反码、补码均相同。所以经过计算c的值为0

eg2.

int a =  6;

int b = -7;

int c =a|b;

a的二进制补码序列:

00000000000000000000000000000110

b的二进制补码序列:

11111111111111111111111111111001

c的二进制补码序列:

11111111111111111111111111111111

c的二进制原码序列:

10000000000000000000000000000001

因为c的二进制补码序列显示c为负数,所以c的二进制原码、反码、补码各不相同,写出原码后得出c=-1。

eg3.

int a = 6;

int b = 7;

int c=a∧b;

a的二进制补码序列:

00000000000000000000000000000110

b的二进制补码序列:

11111111111111111111111111111001

c的二进制补码序列:

11111111111111111111111111111111

c的二进制原码序列:

10000000000000000000000000000001

经过计算c=-1。

eg4.

int a= 0;

int b = ~a;

printf("%d",b);

a的二进制补码序列:

00000000000000000000000000000000

b的二进制补码序列:

11111111111111111111111111111111

b的二进制原码序列:

10000000000000000000000000000001

经过计算b=-1。

(4)   位操作符的项目例子

eg1.不能创建临时变量,交换两个数的数值。

法一:

int a=3;

int b=5;

a=a+b;

b=a-b;

a=a-b;

法二:

a=a∧b;//a=3∧5

b=a∧b; //b=3∧5∧5其中5∧5为0,则b最终为3。

a=a∧b; //a=3∧5∧3其中3∧3为0,则a最终为5。

总结:a∧0等于a,a∧a等于0。且∧操作符支持交换律。

eg2.编写代码求出一个整数存储在内存中二进制1的个数

法一:

根据10进制和2进制之间的转化规则编写。10进制转化为2进制,需要将10进制数不断除以2得出余数,所得余数便是2进制序列不同位的数字。

# include

int  count_bit_one  ( int n )//定义一个函数用于计算一个数字二进制序列中1的个数

{

int count=0;//定义一个计数器

while(n)//定义一个while循环,当n等于0时循环停止

{

if(n%2==1)//如果n对2求余为1

 count++;//则计数器加一

n=n/2;//最后n除以2,继续进入循环。

}

return count;//函数返回值为count

}

int main ( )

{

int num = 0;//定义并且初始化要求的变量num

scanf("%d",&num);//读取键盘输入的数据,存入num变量中

int  ret=count_bit_one( num );//将函数返回值赋值给ret变量

printf("%d",ret);//打印ret的值,此值便是需求的答案

return 0;

}

法二:

根据已学的操作符>>和&进行编写。将需要求的数字>>i,然后&1。于是可以知道该数字num的最右位是否为1。

int count _bit _one ( int n )//定义一个函数用于计算一个数字的二进制序列中1的个数

{

for (int i=0;i<32;i++)//因为定义了一个整数为32个bit位,所以定义一个循环。使i从1增加到32。

{

if((n>>1)&1==1)//具体解释见上

count ++;//计数器加一

}

return count;//返回计数器的数值

}

法三:

根据位操作符&不断将num的最右端二进制序列的1变为0,同时计数器加一。

拓展:如何将一个数值的二进制序列的最右端数字从1变成0?————→需要n&(n-1)

int count_bit_one(int n)

{

int count =0;//定义一个计数器变量count

 while(n)//定义一个循环,当n的二进制序列的每一位数字均为0时,跳出循环。

{

n&(n-1);

count++;//计数器加一

}

return count;//返回计数器的值

}

eg3.写一个代码,判断n是否为2的次方数。

拓展:2的次方数的二进制序列只有一位是1,其余位均为0,当该数的最右端二进制序列1被消去后,则该数变为0。

if(n&(n-1)==0)

printf("yes");

eg4.写一个代码,将13的二进制序列的第5位改为1之后又改为0。进而拓展为第n位。

13的二进制补码序列为:

00000000000000000000000000001101

1<<5-1

00000000000000000000000000010000

第一轮变化之后数的二进制补码序列为:

00000000000000000000000000011101

~1<<5-1

11111111111111111111111111101111

上述两者|,便可以将第五位进行替换

# include

int main ( )

{

int a=13;

int n=5;

a=a|((n-1)>>1);//将a和1向左移n-1位的数进行按位或

a=a&~((n-1)>>1);//将a和1向左n-1位的数进行按位取反后按位与。

return 0;

}


3.   单目操作符

(1)   特点:只有一个操作数

(2)   分类:!++   --  &    *   +    -   ~  sizeof (强制类型转化)

其中&为取地址操作符,*为解引用操作符。


4.逗号操作符

(1)   书写形式:表达式一,表达式二……(从左至右依次计算)

(2)   eg.

int main( )

{

int a=1;

int b=2;

int c=(a>b,a=b+10,a,b=a+1);

printf("%d",c);

}

计算结果为c=13

结论:逗号表达式的结果为最后一个表达式的计算结果,计算顺序为从左至右。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(C语言学习,c语言,算法,学习)