0

在尝试将short提升为int时,我遇到了一些奇怪的行为,其中提升后的高 2 个字节为 0xFFFF。AFAIK 高字节应始终保持为 0。请参见以下代码:

    unsigned int test1 = proxy0->m_collisionFilterGroup;
    unsigned int test2 = proxy0->m_collisionFilterMask;
    unsigned int test3 = proxy1->m_collisionFilterGroup;
    unsigned int test4 = proxy1->m_collisionFilterMask;

    if( test1 & 0xFFFF0000 || test2 & 0xFFFF0000 || test3 & 0xFFFF0000 || test4 & 0xFFFF0000 )
    {
        std::cout << "test";
    }

一旦cout被命中,所涉及的变量的值是:

奇怪的促销

请注意两个突出显示的值。我还查看了对我来说也很好的反汇编:

拆卸

我的软件针对使用 VS 2008 SP1 编译的 x64。我还链接了 Bullet Physics 2.80 的开箱即用版本。代理对象是子弹对象。

代理类定义如下(去掉了一些函数):

    ///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. 
///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{

BT_DECLARE_ALIGNED_ALLOCATOR();

    ///optional filtering to cull potential collisions
    enum CollisionFilterGroups
    {
            DefaultFilter = 1,
            StaticFilter = 2,
            KinematicFilter = 4,
            DebrisFilter = 8,
            SensorTrigger = 16,
            CharacterFilter = 32,
            AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
    };

    //Usually the client btCollisionObject or Rigidbody class
    void*   m_clientObject;
    short int m_collisionFilterGroup;
    short int m_collisionFilterMask;
    void*   m_multiSapParentProxy;      
    int         m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.

    btVector3   m_aabbMin;
    btVector3   m_aabbMax;

    SIMD_FORCE_INLINE int getUid() const
    {
        return m_uniqueId;
    }

    //used for memory pools
    btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
    {
    }

    btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
        :m_clientObject(userPtr),
        m_collisionFilterGroup(collisionFilterGroup),
        m_collisionFilterMask(collisionFilterMask),
        m_aabbMin(aabbMin),
        m_aabbMax(aabbMax)
    {
        m_multiSapParentProxy = multiSapParentProxy;
    }
}
;

我以前从未遇到过这个问题,只是在升级到 64 位并集成子弹后才开始得到它。我遇到问题的唯一地方是涉及子弹的地方,所以我怀疑这个问题与此有关,但我仍然对什么可能使原始类型之间的分配不符合预期感到非常困惑。

谢谢

4

2 回答 2

3

您正在请求从已签名到未签名的转换。这是非常直截了当的:

  • 您的源值为-1. 由于类型是short int,在您的平台上有位0xFFFF

  • 目标类型是unsigned int-1不能表示为无符号整数,但转换规则由标准定义:选择与-1模 2 N一致的正值,其中N是无符号类型的值位数。

    在您的平台上,unsigned int有 32 个值位,因此-1模 2 32的模代表是0xFFFFFFFF.

如果您自己的想象规则在哪里应用,您会想要结果0x0000FFFF,即 65535,并且与 -1 没有任何明显或有用的关系。

如果您确实想要这种转换,则必须手动对短类型执行模块化环绕:

short int mo = -1;
unsigned int weird = static_cast<unsigned short int>(mo);

简而言之: C++ 是关于的,而不是关于表示的。

于 2012-09-14T09:38:02.823 回答
0

AFAIK 高字节应始终保持为 0

当使用从 short 到 int 算术移位(也称为有符号移位)时,要回答您的问题,知道它是通过对添加的字节数进行最大字节值的扩展来执行的就足够了;

例子:

short b;
int a = b; /* here promotion is performed, mechanism of it can be described by following bitwise operation: */
a = b >> (sizeof(a) - sizeof(b)); // arithmetic shift performed

重要的是要注意,在计算机内存中,有符号和无符号值的表示可以相同,编译器生成的命令的唯一区别是:

例子:

unsigned short i = -1 // 0xffff
short j = 65535 // 0xffff

所以实际上有符号/无符号对于提升的结果并不重要,在这两种情况下都会执行算术移位

于 2012-09-14T07:38:53.283 回答