本篇文章给大家分享的是有关C语言中怎么实现位操作,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
C语言中提供了&(与)、|(或)、^(异或)、~(取反)、>>(右移)、<<(左移)6种位操作符。我们可以在程序中合理地使用这些位操作符号来提高程序的运行效率,例如,对于下面的示例代码: intx=0; inty=0; x=257/8; y=456%32;
intx=0;
inty=0;
x=257>>3;
y=456-(456>>4<<4);
这样就可以使程序在性能上得到一定提升。
尽量避免对未知的有符号数执行位操作
在C语言中,如果在未知的有符号数上执行位操作,很可能会导致缓冲区溢出,从而在某些情况下导致攻击者执行任意代码,同时,还可能会出现出乎意料的行为或编译器定义的行为。
下面来看一个简单的示例:
#include
intmain(void)
{
intx=0;
inty=0x80000000;
charbuf[sizeof("128")];
x=sprintf(buf,"%u",y>>24);
if(x==-1||x>=sizeof(buf))
{
//错误处理
}
printf(buf);
return0;
}
代码中,y>>24的执行结果为4294967168,而sizeof(buf)的结果为4。当我们将y>>24的结果值转换为字符串“4294967168”时,超出了buf范围,所以结果值无法完全存储在buf中。因此,在执行语句“x=sprintf(buf,"%u",y>>24)”时,sprintf方法在进行写操作时就会越过buf的边界,从而产生缓冲区溢出。
如果在编译器VC++中执行这段程序,将会产生错误报告。
在C99中,要修正这样的错误,最好利用snprintf方法来代替sprintf方法。因为snprintf方法最多从源串中复制n-1个字符到目标串中,然后再从后面加一个0。因此,如果目标串的大小为n,将不会产生溢出。
即将:
inty=0x80000000;
修改为:
unsignedinty=0x80000000;
那么这种缓冲区溢出错误将不会发生。
在右移中合理地选择0或符号位来填充空出的位
在右移运算中,空出的位用0还是符号位进行填充呢?
其实答案由具体的C语言编译器实现来决定。在通常情况下,如果要进行移位的操作数是无符号类型的,那么空出的位将用0进行填充;如果要进行移位的操作数是有符号类型的,则C语言编译器实现既可选择0来进行填充,也可选择符号位进行填充。
因此,如果很关心一个右移运算中的空位,那么可以使用unsigned修饰符来声明变量,这样空位都会被设置为0。同时,如果一个程序采用了有符号数的右移位操作,那么它就是不可移植的。
移位的数量必须大于等于0且小于操作数的位数
如果被移位的操作数的长度为n,那么移位的数量必须大于等于0且小于n。因此,在一次单独的操作中不可能将所有的位从变量中移出。例如,一个int型的整数是32位,并且n是一个int型整数,那么n<<31和n<<0是合法的,但n<<32和n<<-1是不合法的。因此,我们在进行移位运算的时候必须做相关测试。示例代码如下所示: y="">=sizeof(unsignedint)*CHAR_BIT)
{
//错误处理
}
else
{
result=x>>y;
}
这里还需要说明的是,对于变量x与y,C99规定:
对于x<y可以用结果类型表示,那么这个表达式就是结果值,否则,其行为是未定义的;如果x是无符号类型,则x
虽然位操作在很大程度上可以提高程序的执行效率,但在同一个变量上执行位操作和算术运算会模糊程序员的意图,削弱代码的可移植性与可读性,还会导致安全审核员或代码维护人员难以确定应该执行什么检查以消除安全缺陷,保证数据的完整性。
以上就是C语言中怎么实现位操作,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。