1

我在 Windows 8 64 位上使用 Visual Studio 2012。我有这两种方法:

void Node::setState(States state, bool value) {
    if (value) {
        states_ |= 1 << state;
    }
    else {
        states_ &= ~(1 << state);
    }
}

bool Node::getState(States state) {
    return (states_ & (1 << state)) != 0;
}

状态枚举:

enum States {
    UPDATABLE = 0x01, // Node data update.
    RENDERABLE = 0x02, // Node rendering on screen.
    TRANSFORMABLE = 0x04, // Position, rotation and scaling update.
    POSITION = 0x08, // Position update.
    ROTATION = 0x10, // Rotation update.
    SCALING = 0x20 // Scaling update.
};

状态整数初始化:

states_(TRANSFORMABLE | RENDERABLE |
            UPDATABLE | POSITION | ROTATION | SCALING)

现在问题出在这部分代码中:

LOGI("SETTING SCALING FOR NODE: %s", node->getName().c_str());
node->setState(Node::SCALING, true);
if (node->getState(Node::SCALING)) {
    LOGI("NODE WILL BE UPDATED.");
}
else {
    LOGI("NODE WILL NOT BE UPDATED.");
}

在调试模式下,我得到“节点将被更新”,在发布时 - “节点将不会被更新”。这是什么原因造成的?

4

3 回答 3

2

SCALING是一个 32 位有符号整数,其值为0x20。您将左移1( 0x2032) 个位。这意味着您将其移动得太远,导致未定义的行为。

标准的相关引用:

E1 << E2 的结果是 E1 左移 E2 位位置;空出的位用零填充。如果 E1 具有无符号类型,则结果的值为 E1×2E2,比结果类型中可表示的最大值多模一减少。如果 E1 具有带符号类型和非负值,并且 E1×2E2 在结果类型中是可表示的,那么这就是结果值;否则,行为是未定义的。

于 2013-03-08T06:35:31.530 回答
1

的值States是位掩码,而不是移位值。

将它们更改为移位值:

enum States {
    UPDATABLE = 0, // Node data update.
    RENDERABLE = 1, // Node rendering on screen.
    TRANSFORMABLE = 2, // Position, rotation and scaling update.
    POSITION = 3, // Position update.
    ROTATION = 4, // Rotation update.
    SCALING = 5 // Scaling update.
};

并适当修改初始化states_;或将它们用作掩码:

void Node::setState(States state, bool value) {
    if (value) {
        states_ |= state;
    }
    else {
        states_ &= ~state;
    }
}

bool Node::getState(States state) {
    return (states_ & state) != 0;
}    
于 2013-03-08T06:38:57.317 回答
1

我猜 states_ 是一个 32 位整数。您对 setState 和 getState 的实现没有达到您的预期。请注意, setState(SCALING) 将向左移动 1 个 0x20 (= 32) 位。如果您有一个 32 位整数,那将产生未定义的结果(请参阅http://msdn.microsoft.com/en-us/library/336xbhcz(v=vs.71).aspx)。因此,代码优化器(在这种情况下可能是调试和发布版本之间的重要区别)可以自由地做一些与未优化代码不同的事情。

鉴于您对States 值的定义,setState 应该只是 states_ |= state(或 &= ~state)。同样,getState 应该只返回 states_ & state。

于 2013-03-08T06:47:07.533 回答