繁体   English   中英

为什么在C ++中使用按位运算

[英]Why using Bitwise operations in c++

我很难理解为什么要在枚举中然后在代码中使用按位运算。 为什么不只使用数字或布尔值例如:

enum
{
    RS_BLEND = (1 << 0),
    RS_BLEND_FUNC = (1 << 1),
    RS_CULL_FACE = (1 << 2),
    RS_DEPTH_TEST = (1 << 3),
    RS_DEPTH_WRITE = (1 << 4),
    RS_DEPTH_FUNC = (1 << 5),
    RS_CULL_FACE_SIDE = (1 << 6),
//            RS_STENCIL_TEST = (1 << 7),
//            RS_STENCIL_WRITE = (1 << 8),
//            RS_STENCIL_FUNC = (1 << 9),
//            RS_STENCIL_OP = (1 << 10),
    RS_FRONT_FACE = (1 << 11),

    RS_ALL_ONES = 0xFFFFFFFF,
};


void RenderState::StateBlock::setCullFace(bool enabled)
{
    _cullFaceEnabled = enabled;
    if (!enabled)
    {
        _bits &= ~RS_CULL_FACE;
    }
    else
    {
        _bits |= RS_CULL_FACE;
    }
}

这不是关键或嵌入式软件。

使用位而不是布尔值的优点是您可以直接操作值集 例如定义:

const int FILLED  = (1 << 0);
const int STROKED = (1 << 1);
const int SHADOW  = (1 << 2);
const int BLINK   = (1 << 3);

您可以有一个接受draw_mode参数的函数并像这样调用它

draw_symbol(FILLED | SHADOW | BLINK, "X");

即直接传递值的子集。

使用容器而不是单个整数参数将需要更多的代码来写入和读取。 它的效率也会降低,但是在某些情况下这不是最重要的一点。

这些枚举值是_bits域(此处为_bits )中使用的标记 通过声明布尔值的结构可以获得类似的行为:

struct field {
    bool rs_blend;
    bool rs_blend_func;
    ...
};

但是,这样的结构每个条目至少需要一个字节,并且处理起来很笨拙,因此开发人员通过将这些值编码为整数值的位来采用了不同的方法。

值1的任何整数都设置了“最右边”(最低有效)位,因此1 << ii位数正好等于1,这意味着该枚举中的每个常量( RS_BLENDRS_BLEND_FUNC )都编码一位。 这实际上是一个相当普遍的习惯用法,尤其是在C语言中,处理结构更为冗长。

通过使用按位运算,可以立即在该位域中设置或清除等。 例如RS_BLEND | RS_BLEND_FUNC RS_BLEND | RS_BLEND_FUNC创建一个恰好设置了这两个标志的位域。 这个线程关于位运算的在这方面的使用细节。

如果您使用布尔值,则为1位和8位。 使用1/8的内存可以代表相同的数据,这是非常了不起的节省(并且由于有人不习惯按位操作而使用8倍的内存同样非常浪费),如果您经常处理热数据,那可能很重要循环访问(我的i7上每个内核的L1缓存只有64KB,例如,更不用说有限的寄存器了)。

此外,如果在此处使用位,则可以测试通过一条指令设置的两个或更多位。 您也可以一次使用FFZ / FFS在64位中高效地找到一个空闲位或一个设置位。 例如,您可以轻松地一次转换64位,而不必循环遍历64个布尔值,而一次执行一次,这不仅对CPU效率极高,而且对开发人员写出全部效率低下,效率高当他只能使用一个运算符时的代码。

好处不断。 我实际上认为更多的人应该使用按位运算,而不是更少。 习惯于按位思考需要花费一些时间,但是并不需要花费太长时间。

很方便。

在示例代码中,显然(包括注释中的内容)至少包含12个不同的设置,每个设置都可以打开或关闭,但是可以组合使用。

位摆弄允许打开或关闭各个设置的组(包括一组),或测试特定组是否打开或关闭而不必大惊小怪。

数字值和数字运算可以做到这一点,但并不方便。

例如,使用以下命令更容易(且更不容易出错)来测试是否至少启用了CULL_FACE和DEPTH_FACE设置之一

 if (flags & (RS_CULL_FACE | RS_DEPTH_FACE))

而不是跟踪所有可能的数值,对于这两个设置,其中之一可能是真实的,并针对每个数值进行测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM