C语言细讲——运算符(穿插整形提升与算术转换)

本博文接着细讲述C语言的下一个知识点:运算符。
作者:小 琛
欢迎转载,请标明出处

引言:给操作符一个简单的分类:
算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用、函数调用和结构成员。

算术操作符

+ - * / %
·%运算符不可用于浮点型数据
· 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。

移位操作符

’<< ‘ 左移操作符
‘>> ’右移操作符
1、 左移操作符 移位规则: 左边抛弃、右边补0
例如:9在计算机的储存为:0000 0000 0000 0000 0000 0000 0000 1001
若左移一位,为: 0000 0000 0000 0000 0000 0000 0001 0010

右移操作符

1、逻辑移位 左边用0填充,右边丢弃
2、算术移位 左边用原该值的符号位填充,右边丢弃
注意: 对于移位运算符,不要移动负数位

位操作符

位操作符有:
& 按位与、 | 按位或 ^按位异或
注:他们的操作数必须是整数
1、按位与的操作规则是参与运算的两数(若不是二进制则先转换为二进制)对应二进位相与,若对应的二进制位都为1,则结果的相应二进位为1,否则为0。
例如如下代码:

int main()
 {    
 int i=0;
 int num1 = 1;   
 int num2 = 2;   
 i=num1 & num2;    
 printf("%d", i);
 return 0; 
 }

结果i的值为0
另外,在按位与操作中,任何数与-1相与结果都是那个数本身,任何数与0相与结果都为0。按位与运算通常用来对某些位清0或保留某些位。
2、按位或的操作规则是参与运算的两数(若不是二进制则先转换为二进制)对应二进位相或,只要对应的二进制位一个为1,其结果的相应二进位就为1,否则为0。此处参照按位与的例子,笔者就不列举了。
3、按位异或的操作规则是参与运算的两数(若不是二进制则先转换为二进制)对应二进位相异或,若对应的二进制位一个为1,但另一个不为1则结果的对应二进位为1,否则为0。

接下来看一道面试题:
1、不能创建临时变量(第三个变量),实现两个数的交换。
分析:该题表明不允许借助其他变量,那么一定是使用其它的位运算手段来实现的

#include <stdio.h> 
int main() 
{   
 	int a = 10;    //a的二进制:0000 0000 0000 0000 0000 0000 0000 0000 1010
 	int b = 20;    //b的二进制:0000 0000 0000 0000 0000 0000 0000 0001 0100
	a = a^b;       //运算完成后:0000 0000 0000 0000 0000 0000 0000 0001 1110
	b = a^b;       //运算完成后:0000 0000 0000 0000 0000 0000 0000 0000 1010
 	a = a^b;       //运算完成后:0000 0000 0000 0000 0000 0000 0000 0001 0100
 	printf("a = %d  b = %d\n", a, b);    
 	return 0; 
 }

操作符
+=
-=
*=
/=
%=
’>>=
<<=
&=
|=
^=
例如a+=b;表示a=a+b;依次类推

单目操作符

’!‘ 逻辑反操作
‘-‘ 负值
’+‘ 正值
‘&’ 取地址
’sizeof‘ 操作数的类型长度(以字节为单位)
‘~’ 对一个数的二进制按位取反
‘–’ 前置、后置-
’++‘ 前置、后置++
‘*’ 间接访问操作符(解引用操作符) (类型) 强制类型转’

关系操作符

‘>’、’>=‘、’<‘、’<=’、‘==‘

注意:这里的等于‘==’很容易和赋值‘=’搞混淆

逻辑、条件操作符

1、逻辑操作符:
&&逻辑与 ||逻辑或
区分逻辑与和按位与 区分逻辑或和按位或
一个是位运算,针对的是该数的二进制,另一个是逻辑运算,针对该数本身
现在看一组代码,分析结果:

#include <stdio.h>
int main() 
{    int i = 0,a=0,b=2,c =3,d=4;   
     i = a++ && ++b && d++;    
     printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);    
     return 0; 
 }

结果:
1
2
3
4
总结:当第一个逻辑&&为假时候,不再继续执行
2、条件操作符
exp1 ? exp2 : exp3
使用方法:exp1为真否?为真,exp2,否则exp3

这里穿插知识点整形提升和算术转换:
1、整形提升
C的整型算术运算总是至少以缺省整型类型的精度来进行的,因此在每次运算时要保证足够整形精度。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
例如:

int main() 
{    
char a = 0xb6;    short b = 0xb600;    int c = 0xb6000000;    
if(a==0xb6)        
printf("a");    
if(b==0xb600)        
printf("b");   
 if(c==0xb6000000)       
 printf("c");    
  return 0;
   } 

结果:只输出了c,a与b发生了整形提升

算术转换:
算术类型的转换,尽可能转换为当前的最大类型

练习题:
1、编写代码实现:求一个整数存储在内存中的二进制中1的个数。
分析:同样可以使用位操作,将该数进行右移,每右移一次与1进行逻辑与运算,并加以计数

#include <stdio.h> 
int count_one_bits(unsigned int value)
{   
 int count = 0;
 for (int j = 0; j < 32; j++)
 {
  if (value & 1)
   count++;
  value = value >> 1;
 
 }
 return count;
 }
int count_one_bits2(unsigned int value)  //更高端的方法
{
  int count=0;
  while (value)
{
  count++;
  num = num&(num-1); 
}
}
int main()
{
 unsigned int num = 0;
 int i = 0;
 scanf("%d",&num);
 i = count_one_bits(num);
 printf("该数二进制中1的个数为%d", i);
 return 0;
}

2、获取一个数二进制序列中所有的偶数位和奇数位,分别输出二进制序列。

#include <stdio.h> 
void Get_Print(unsigned int value)
{   
 int arr[32] = { 0 };
 int i = 0;
 while (value != 0)
 {
  arr[i++] = value % 2;
  value /= 2;
 }
 printf("该数的奇数位为:");
 for (i = 30; i >=0; i -= 2)
 {
  printf("%d   ", arr[i]);
 }
 printf("\n");
 printf("该数的偶数位为:");
 for (i = 31; i >=0; i -= 2)
 {
  printf("%d   ", arr[i]);
 }
}
void Get_Print1(unsigned int value)
{
	int i=0;
	printf("奇数为:\n")
	for (i=31;i>=1;i-=2)
	{
		printf("%d ",((value>>i)&1));	
	}
	printf("\n偶数为:\n");
	for(i=30;i>=0;i-=2)
	{
		printf("%d",((value>>i)&));
	}
}
int main()
{
 int num = 0;
 printf("请输入一个数\n");
 scanf("%d",&num);
 Get_Print(num);
 return 0;
}

3、输出一个整数的每一位。例如:2 输出0000 0000 0000 0000 0000 0000 0000 0010
也可以将此题理解为将一个数转化为32位的二进制

#include <stdio.h> 
void Get_result(int arr[],int i)
{   
 int j = 0;
 while (i != 0)
 {
  arr[j++] = i % 2;
  i /= 2;
 }
}
int main()
{
 int arr[32] = { 0 };
 int num = 0,i=31,j=0;
 printf("请输入一个数\n");
 scanf("%d", &num);
 Get_result(arr, num);
 for (; i >=0; i--,j++)
 {
  if (j % 4 == 0&&j!=0)
   printf("   ");
  printf("%d", arr[i]);
 }
 return 0;
}

4、
两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
输入例子:
1999 2299
输出例子:7
提示:使用异或会简化

#include <stdio.h> 
int Get_num(int i,int j)
{   
 int num = 0,count=0;
 num = i^j;
 while (num != 0)
 {
  if (num % 2 == 1)
   count++;
  num /= 2;
 }
 return count;
}
int main()
{
 int m, n;
 int result = 0;
 printf("请输入两个数\n");
 scanf("%d%d", &m, &n);
 result=Get_num(m, n);
 printf("共有%d个不同\n", result);
 return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值