簡體   English   中英

如何在unsigned int上使用bitflag以便在其中存儲額外的bool值

[英]How to use a bitflag on an unsigned int in order to store an additional bool value in it

我在游戲中使用代表一組飛機的無符號整數。 每架飛機都有兩種狀態,飛行和接地。 我想將這個狀態與飛機號碼一起存儲。 實現這一目標的“最佳”方式是什么? 我可以使用std :: maps與飛機及其狀態,但這似乎有點過分和緩慢。 可以用位標志來完成嗎? 測試的分配和測試應該很快。

偽代碼:

unsigned int Boing = 777;

if( Boing is flying)
 set some bit;

is Boing flying? (how to check for the current state)

任何關於簡單快速技術的暗示都值得贊賞!

最快和最干凈的方法可能是避免使用位域,只需定義一個結構:

struct Plane
{
    bool isFlying;
    unsigned int number;
}

...


std::vector<Plane> planes;
Plane p;
p.isFlying = true;
p.number = 777;
planes.push_back(p);

此方法將使用更多的內存,而不是嘗試將標志塞入同一個單詞,但獲取/設置字段所需的工作量較少。 除非你受到內存限制,否則我強烈建議避免嘗試緊緊包裝所有內容。

您甚至可以考慮使用enum而不是bool來表示州。

一種簡單的方法是,如果不飛行,只需將數字設為負數。

struct Stuff
{
  unsigned int Boing: 31;
  unsigned int isFlying: 1;
};

.
.
.

Stuff myStuff;
myStuff.Boing = 777;
myStuff.isFlying = false;

有關位域的更多信息

假設您從未使用unsigned int中可用的全部值(合理的可能性,但絕對不確定),您可以將范圍限制為比包含無符號的位少一位,然后使用最高位來存儲“飛行”狀態。 在這種情況下,您可以執行以下操作:

// This theoretically isn't required to work, but will for most reasonable machines.
unsigned flying_bit = 1 << (CHAR_BITS * sizeof(unsigned));

void take_off(unsigned &plane) {
    plane |= flying_bit;
}

void land(unsigned &plane) { 
    plane &= flying_bit;
}

bool is_flying(unsigned const &plane) { 
    return plane & flying_bit != 0;
}

另一種可能性是使用實際的位域:

struct plane { 
    uint32_t model: 31;
    uint32_t flying: 1;
};

在這種情況下,您只需直接指定值,例如:

plane myplane = {777, 0};

myplane.flying = 1; // take off

myplane.flying = 0; // land

為什么不簽署你的整數? 正值是飛行,負值不是,零是無效的。

使用結構或類來組合信息“數字”和“狀態”,以及您想要的任何平面。 如果對int使用位操作(這是可能的,只是不可取),更改狀態將改變實際的平面數。

假設你的unsigned int有32位:

#define SET_FLYING(x)     (x) |= (1<<31)
#define SET_GROUNDED(x)   (x) &= ~(1<<31)
#define IS_FLYING(x)      ((x) & (1<<31))
#define ID(x)             ((x) & ~(1<<31))

如果你想要更加時尚的c ++,你可以把它們寫成內聯函數。 無論如何,我寫了更多來向你展示如何進行位操作,而不是將其實現為宏還是函數。

要使其適用於不同大小的int,您可以將31更改為:

instead of 31: ((sizeof(x)<<3)-1)

這基本上是sizeof(x)*8-1

PS如果有人想告訴我“不不!不要使用宏,這是C ++,使用我寫的這個過於復雜的東西”,省去你的呼吸。 只需給-1並繼續前進。

編輯 :我上面寫的是你的問題的答案:“如何使用符號位作為標志”。 如果你想以更好的方式做到這一點,但不擴展你的內存使用量(通過添加bool ),你總是可以寫這樣的東西:

struct airplane
{
    unsigned int id: 31;
    unsigned int is_flying: 1;
};

airplane Boing = {777, false};

然后,分配和讀取idis_flying執行位操作,但它們由編譯器處理。

您可以將狀態和平面編號打包在unsigned int中 假設unsigned int在您的平台上是32位

unsigned int myplane;
int planenumber = (myplane & 0xffff ) //can be the plane number
int booleanstate = ((myplane >> 16) & 0xffff) //can be the boolean state

使用bitset索引作為平面編號的bitset怎么樣? 如果您不需要更多狀態,那么您就完成了。 如果你需要,你也可以使用每個狀態(例如崩潰,修復需要一個單獨的位向量,所以你只需要為你實際需要的每個平面狀態使用一個位。

但我懷疑,如果你處理游戲圖形,物理速度會成為你的主要考慮因素,與飛機狀態下的操作相比,物理會占用大部分CPU時間。

#include <iostream>
#include <boost/dynamic_bitset.hpp>

using namespace boost;

class State
{
public:
    State(int nPlanes):_States(dynamic_bitset<>(nPlanes))
    {
    }

    void SetState(int nPlane, bool bFly)
    {
        _States[nPlane] = bFly;
    }

    void Dump()
    {
        for (boost::dynamic_bitset<>::size_type i = 0; i < _States.size(); ++i)
            std::cout << _States[i];
    }

private:
    dynamic_bitset<> _States;
};


int _tmain(int argc, _TCHAR* argv[])
{
    State planes(500);
    planes.SetState(0, true);
    planes.SetState(5,true);
    planes.Dump();

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM