位运算的使用
1.输入一个float型数,以十六进制形式输出其32位机器数。#include
void main()
{
float a;
int *p;
printf("Input a float number:\n");
scanf("%f",&a);
p=(int *)&a;
printf("%X",*p);
}
2.从键盘输入一个二进制非负整数,屏幕上打印输出对应的十进制、八进制和十六进制数,要求输出的十六进制数中的英文字母为大写字母。
#include
void main()
{
int ConvertBinaryToDecimal(long long n);//二进制转十进制的函数声明
long long n;
printf("Input a binary number:\n");
scanf("%lld",&n);//从键盘读取一个二进制数
long long m;
m=ConvertBinaryToDecimal(n);//调用函数
printf("The number is %d in decimal.\n",m);//输出十进制数
printf("The number is %o in octal.\n",m);//输出八进制数
printf("The number is %X in hexadecimal.\n",m);//输出十六进制数
}
int ConvertBinaryToDecimal(long long n)
{
int i=1,j,sum=0;//i表示位权,j表示每一次循环取出的尾数,sum表示转换的十进制数
while(n!=0)
{//循环条件为n不等于0
j=n%10;
sum+=j*i;
n/=10;
i*=2;
}
return sum;
}
3.定义函数void DecToBin(int a, char b); 函数功能是将整数a转换为它对应的32位二进制机器数,将32位二进制机器数以字符串形式存于字符数组b(以'\0'字符结束)不允许使用%2运算,只能利用位运算符(如:移位运算,与运算等)实现程序功能。
#include
void main()
{
void DecToBin(int a,char b);//函数声明
int n,i=0;char b;
scanf("%d",&n);//从键盘读取一个数
DecToBin(n,b);//函数调用
}
void DecToBin(int a,char b)
{
int i;
if(a>=0)//当a大于零时,直接通过位运算求其32位2进制机器数
{
for(i=0;i
b='\0';
i=0;
while(a!=0)
{
b=a&1;
a=a>>1;
}
}
else//当a小于零时,先求其绝对值的机器数,再每位取反,再最后一位加1
{
for(i=0;i
b='\0';
a=-a;
i=0;
while(a!=0)
{//每位取反
if((a&1)==0)
b=1;
else
b=0;
a=a>>1;
}
b+=1;//最后一位加1
i=0;
while(b==2)//判断是否需要进位
{
b=0;
b[++i]+=1;
}
}
for(i=31;i>=0;i--)
printf("%d",b);//输出
printf("\n");
}
4.定义函数unsigned mod(unsigned a, unsigned b, unsigned c); 功能是计算并返回a*b%c的结果。要求考试a, b, c的范围是大于0且小于 231,程序不能使用64位整型(如:long long类型或__int64)求解。
#include
void main()
{
unsigned mod(unsigned a, unsigned b, unsigned c);//函数声明
unsigned a,b,c;
printf("Input unsigned integer numbers a, b, c:\n");
scanf("%u%u%u",&a,&b,&c);//输入
printf("%u*%u%%%u=%u\n",a,b,c,mod(a,b,c));//输出
}
unsigned mod(unsigned a, unsigned b, unsigned c)
{
int i;
int bin=;
i=0;
while(b!=0)
{//求b的32为二进制数存入数组bin中
bin=b&1;
b=b>>1;
}
unsigned result=a*bin;//初始化result的值
for(i=31;i>0;i--)
result=(result
result=result%c;
return result;//返回result
}
有符号数右移问题 不要依赖未定义的行为,如移位操作的溢出行为。 位运算 是直接对整数的二进制位进行操作的高效方法,包括按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、右移(>>)等操作。 虽然位域可以节省内存,但其具体实现可能因编译器而异,跨平台时可能出现问题。 位运算的优先级低于算术运算,但高于逻辑运算。 描述各种位运算的具体行为,如按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、右移(>>)。 包括运算符优先级、有符号数的符号位处理、溢出问题、可移植性问题以及代码可读性。 不要使用位运算来检查一个数是否为偶数(如使用num & 1来检查最低位),而应该使用模运算或位运算的结果来判断。 直接将float类型转换为int*可能会导致内存对齐问题,建议使用`memcpy`函数来安全地进行类型转换。 移位超过数据类型位数 位运算可能会使代码难以理解,尤其是在复杂的位操作中。适当注释和清晰的变量命名可以提高代码可读性。 注意操作数的大小和符号,尤其是在进行移位操作时。 不同数据类型的整数在内存中占用的位数可能不同(如int通常占用4字节,即32位,但在某些系统或编译器下可能不同),进行位运算时需考虑数据类型的位数。 理解补码的运算规则对于正确使用位运算至关重要。例如,在进行加法和减法运算时,如果操作数采用补码表示,可以直接使用位运算来实现。但需要注意溢出情况,即当结果超出数据类型能表示的范围时,会产生错误的计算结果。 位运算通常用于整数类型(如int、unsigned int等)。对于非整数类型(如float、double等),直接应用位运算可能导致未定义行为。 位运算在底层编程中至关重要,但使用不当易引入隐蔽错误。 有符号与无符号数混合运算可能导致意外结果。 注意右移操作的符号扩展。 位运算通常比算术运算更快,但在某些情况下,过度使用位运算可能导致代码可读性下降。