首先,我将假设您不打算在单个操作中连续执行这些操作。如果您真的这样做,结果将始终是0xff
,无论输入如何,因此您无需处理输入,将其分解为字段或其他任何事情。所以我假设如果输入中的一对位以 00 开头,那么该字段的最终结果应该是 01,同样如果它是 01,它应该以 10 结束,如果它是 10 它应该最终为 11(然后,您可能会再次调用它,以便每个人都进行下一步,依此类推)。
其次,我要注意这些操作与简单地增加 2 位字段相同。即:0->1、1->2、2->3(和 3,我们可能不理会,尽管您没有指定)。
获取 C 数据类型中的几个位的一种简单方法是使用它的位域支持。在这种情况下,我们将它与联合一起使用,因此我们有一个联合成员可以访问单个字段,另一个可以访问整个字节作为一个单元。
#include <stdio.h>
// depending on how new it is, your compiler may already define this:
typedef unsigned char uint8_t;
struct Foo {
uint8_t a : 2;
uint8_t b : 2;
uint8_t c : 2;
uint8_t d : 2;
};
typedef union {
unsigned char whole;
struct Foo parts;
} val;
所以现在我们可以访问这些片段,让我们编写一些代码来演示如何使用它:
int main(void) {
val a = {.whole = 0xe4};
// replacing 00 with 01, 01 with 10 and 10 with 11 is incrementing, except for 11
if (a.parts.a < 3)
++a.parts.a;
if (a.parts.b < 3)
++a.parts.b;
if (a.parts.c < 3)
++a.parts.c;
if (a.parts.d < 3)
++a.parts.d;
printf("%2.2x\n", a.whole);
}
警告:理论上,写入联合的一个字段,然后从另一个字段读取不会给出明确的结果。然而,实际上,与硬件接口的代码相当常规地执行此类操作。不同的是顺序——(例如)a.parts.a
是a.whole
. 不幸的是,这不仅会因平台而异,而且会因同一平台上的不同编译器而异。另一方面,在您的情况下,这根本不重要。