什么是跨preT位运算符和屏蔽直观的方式?此外,什么是屏蔽用的? [英] What is an intuitive way to interpret the bitwise operators and masking? Also, what is masking used for?

查看:239
本文介绍了什么是跨preT位运算符和屏蔽直观的方式?此外,什么是屏蔽用的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解位运算符,并在我的电脑系统类,现在掩盖。不过我有一些麻烦,他们内在

I'm learning about bitwise operators and masking right now in my computer systems class. However I'm having some trouble internalizing them.

我明白了什么运营商,和放大器;,|,^,>>(两者算术和逻辑移位),和<<这样做,但我不完全得到他们真正用于除了优化乘法和除法运算(>>和<&LT),并检查如果某些位或关闭(&放大器;运营商)

I understand what the operators, &, |, ^, >> (both arithmetic and logical shift), and << DO, but I don't quite get what they're really used for aside from optimizing multiplication and division operations (for >> and <<), and to check if certain bits are on or off (the & operator).

另外,我不明白是做什么用的屏蔽。我知道,这样做X'放大器; 0xFF的用于提取在一个整数x的至少显著位,但我真的不能从该推断如何其他类型的掩模(例如那些在若干提取最左边的1,即获得一个个符号1的数等)被用于

Also, I don't understand what masking is used for. I know that doing x & 0xFF is used to extract the least significant bit in an integer x, but I can't really extrapolate from that to how other kinds of masks (e.g. those that extract the leftmost 1 in a number, that obtain the number of 1s in a number, etc.) are used?

任何人都可以请提供一些线索这光,preferably一些例子?谢谢你。

Could anyone please shed some light on this, preferably with some examples? Thank you.

推荐答案

一个很好的方式,了解位掩码是一个例子,所以我会给之一。比方说,我们有结构的数组:

A good way to understand bitmasks is with an example so I will give one. Lets say we have an array of structs:

struct my_struct {
  int foo;
  int bar;
};

struct my_struct array_of_structs[64]; // I picked 64 for a specific reason I will discuss later

我们将使用这个数组作为一个池,并根据需要这个数组的元素分配,也可以释放。做到这一点的方法之一是在结构中添加使用 布尔成员。

We will use this array as a pool and the elements of this array are allocated as needed and can also be deallocated. One way to accomplish this is to add a used boolean member in the struct.

struct my_struct {
  int foo;
  int bar;
  char used;
};

不过,另一种方式是创建一个位图。由于数组的大小为64,我们只需要这一个单一的64位整数。需要注意的是,你可以,如果你有更多的元素比你在一个单一的数据类型做到位与位图元素的数组做到这一点,但我会忽略此为清楚起见。

But another way is to create a bitmap. Since the array is of size 64, we only need a single 64 bit integer for this. Note that you can do this with an array of elements for the bitmap if you have more elements than you do bits in a single data type but I will omit this for the sake of clarity.

 unsigned long long bitmap;  // Guaranteed to be at least 64 bits (if I recall correctly)

所以,让让每一个位对应一个元素数组中,一个0意味着不使用该位,并使用了1手段。因此,以纪念元素 I 所使用,我们将做到以下几点:

So lets let every bit correspond to an element in our array, a 0 for that bit means not used and a 1 means used. Therefore to mark element i as used we would do the following:

bitmap = bitmap | (1ULL << i);

或更简洁:

bitmap |= (1ULL << i);

(1ULL&LT;&LT; I)的每一位设置为0,除了 I 次位,因此位图| (1ULL&LT;&LT; I)是一样的位图除了 I 个位设置以及(不管是什么previously是)。什么位| =(1ULL&LT;&LT; I); 正在做基本上是说我想设置的 I 个位为1,离开一切它的方式。在 I 日在这里位是用来重新present是否 I 个对象是免费的或不那么什么另一种方式来跨preT这是我想纪念 I 个元素的使用。

(1ULL << i) has every bit set to 0 except the ith bit so bitmap | (1ULL << i) is the same as the bitmap except the ith bit is set as well (regardless of what it previously was). What bitmap |= (1ULL << i); is doing is basically saying I want to set the ith bit to 1 and leave everything else the way it was. The ith bit here is used to represent whether the ith object is free or not so what another way to interpret this is I want to mark the ith element as used.

现在来测试是否元素 I 或不使用,我们将使用&安培;

Now to test if element i is used or not we would use &:

if(bitmap & (1ULL << i)) {
  // i is used
}
else {
  // i is not used
}

位图和放大器; (1ULL&所述;&下;ⅰ)只会是一个非零值,因此真,如果 I 个位也被在设置位图

bitmap & (1ULL << i) will only be a non-zero value, and therefore true, if the ith bit is also set in bitmap.

终于到了标记元素如不使用,我们将做到以下几点:

Finally to mark an element as not used we would do the following:

bitmap = bitmap & ~(1ULL << i);

,或再次以更简洁

or again to be more concise

bitmap &= ~(1ULL << i);

〜(1ULL&LT;&LT; I)将是64位(假设无符号加长为64位),每一个位设置为1,除非 I 个比特。当相与位图,结果是完全相同的位图除了 I 个位将被设置为0。

~(1ULL << i) will be 64 bits (assuming unsigned long long is 64 bits) with every bit set to 1 except with ith bit. When it is anded with bitmap the result is the exact same as bitmap except the ith bit will be set to 0.

人们可能不知道何时使用位图VS一个使用变量。在某些情况下,一个位图可能会更快,虽然它也有可能是慢,我会说你必须测试该协会致力于您的应用程序,如果这部分曾经成为一个真正的瓶颈。一个例子我可以给使用位图作为使用或不使用标记的事情是当你没有一个自定义的结构。具体来说,从我自己的经验,我使用位图在我的操作系统使用或不使用标记物理帧。因为没有结构体,正如我打标是内存本身,位图工作。然而,这不是最高效的寻找空闲帧的条件,但它的工作原理。

One might wonder when to use a bitmap vs a used variable. In some cases a bitmap could be faster although it could also be slower and I would say you have to test which works for your application, if this part ever become a real bottleneck. One example I can give of using a bitmap to mark things as used or not used is when you don't have a custom struct. Specifically, from my own experience, I use a bitmap in my operating system to mark physical frames as used or not used. Since there is not struct, as what I am marking is memory itself, a bitmap works. However, this is not the most efficient in terms of finding free frames but it works.

另一个常见用途是来标记的属性或特性是否为present。这通常被称为一个位标志。例如,假设我们已经有一个标志元素的球员结构。

Another common use is to mark whether a property or attribute is present. This is commonly referred to as a bit flag. For example lets say we have a player struct with a flag element.

struct player {
  // some members
  unsigned long long flag;
};

我们可能会再对这个球员的各种属性,比如是跳跃,游泳,正在运行,已经死了。我们可以创建对应于每个属性位掩码。

We then might have various properties about this player, such as is jumping, is swimming, is running, is dead. We could create bitmasks that correspond to each property.

#define PLAYER_JUMPING  (1ULL << 0)
#define PLAYER_SWIMMING (1ULL << 1)
#define PLAYER_RUNNING  (1ULL << 2)
#define PLAYER_DEAD     (1ULL << 3)

然后用已经证明打开和关闭属性。同样的动作

Then use the similar operations already demonstrated to toggle properties on and off.

struct player my_player;
my_player.flag |= PLAYER_JUMPING; // Mark the player as jumping
my_player.flag &= ~PLAYER_SWIMMING; // Mark the player as not swimming
if(my_player.flag & PLAYER_RUNNING)  // Test if the player is running

最后,在操作之前我没有表现出是按位异或: ^ 。您可以使用此切换属性。

Finally, the on operation I didn't demonstrate before was the bitwise exclusive or: ^. You can use this to toggle a property.

my_player.flag = my_player.flag ^ PLAYER_DEAD; // If player was dead now player is not dead and vise versa

,或再次以更简洁:

or again to be more concise:

my_player.flag ^= PLAYER_DEAD; // If player was dead now player is not dead and vise versa

这只会影响特定的位位掩码设置和所有其他人将被留给他们的previous值,即 X ^ 0 == X 在位水平。

This will affect only the specific bit set in the bitmask and all the others will be left to their previous value, i.e. x ^ 0 == x at the bit level.

在使用位掩码这种方式,你可以用一个按位和测试多个属性。例如,如果你只关心如果玩家正在运行或跳跃,你可以做到以下几点:

When using bitmasks this way you can test multiple properties with one bitwise and. For example if you only care if the player is running or jumping you could do the following:

if(my_player.flag & (PLAYER_RUNNING | PLAYER_JUMPING))  // Test if the player is running or jumping

请注意,几乎每一个编译器将其转换(PLAYER_RUNNING | PLAYER_JUMPING)来一个常数所以这减少了操作次数,因为相对于只有一个结构的成员被检查两个。

Note that almost every compiler will convert (PLAYER_RUNNING | PLAYER_JUMPING) to a single constant so this reduces the number of operations since only one member of the struct is checked as opposed to two.

这篇关于什么是跨preT位运算符和屏蔽直观的方式?此外,什么是屏蔽用的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆