0

shortintに昇格させようとすると、上位 2 バイトが昇格後に 0xFFFF になるという奇妙な動作に遭遇しました。私の知る限り、上位バイトは常に 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がヒットすると次のようになります。

奇妙なプロモーション

ハイライトされた 2 つの値に注意してください。また、私には問題ないように見える逆アセンブリも見ました。

分解

私のソフトウェアは、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. unsigned int として表現することはできませんが、変換規則は標準で定義されています。モジュロ 2 N-1に合同な正の値を選択します。ここで、Nは unsigned 型の値のビット数です。-1

    お使いのプラットフォームでは、 には 32 値のビットがあるため、モジュロ 2 32unsigned intの剰余表現は です。-10xFFFFFFFF

どこに適用するかを独自の架空のルールで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 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 に答える