C 如何将位字段写入整数值?

C 如何将位字段写入整数值?,c,bit-fields,C,Bit Fields,我正在尝试这样做: typedef struct { uint16_t red : 6; uint16_t green : 5; uint16_t blue : 5; } color_t 然后我想得到如下结果: color_t clr; clr.red = 0; clr.green = 10; clr.blue = 15; 并将复合变量clr写入int: int value = clr; // this does not work fprintf(draw, "%4

我正在尝试这样做:

typedef struct {
    uint16_t red : 6;
    uint16_t green : 5;
    uint16_t blue : 5;
} color_t
然后我想得到如下结果:

color_t clr;
clr.red = 0;
clr.green = 10;
clr.blue = 15;
并将复合变量clr写入int:

int value = clr; // this does not work

fprintf(draw, "%4X", value);
我这样做的原因是我想创建橙色、紫色等颜色,并从文件中在屏幕上绘制它们。 在一个文件中,我正在用十六进制格式写一种颜色

另一件事是,我希望稍后在代码中这样做:

if (clr == value) { ... }

或者换句话说,我想比较struct bitfield和int中包含颜色的实际十六进制值的值。

这是一个单独的示例,演示了如何使用并集访问具有位字段的结构的值:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    uint16_t red: 6;
    uint16_t green: 5;
    uint16_t blue: 5;
} color_t;

typedef union {
    uint16_t color_value;
    color_t color_bits;
} color_helper_t;

int main(void) {
    color_helper_t clr;

    clr.color_bits.red = 0;
    clr.color_bits.green = 0;
    clr.color_bits.blue = 15;

    uint16_t value = clr.color_value;

    printf("%04X\n", value);

    if (clr.color_value == value) {
        printf("The values are equal\n");
    }

    return 0;
}

这是一个单独的示例,演示了如何使用并集访问具有位字段的结构的值:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    uint16_t red: 6;
    uint16_t green: 5;
    uint16_t blue: 5;
} color_t;

typedef union {
    uint16_t color_value;
    color_t color_bits;
} color_helper_t;

int main(void) {
    color_helper_t clr;

    clr.color_bits.red = 0;
    clr.color_bits.green = 0;
    clr.color_bits.blue = 15;

    uint16_t value = clr.color_value;

    printf("%04X\n", value);

    if (clr.color_value == value) {
        printf("The values are equal\n");
    }

    return 0;
}

我认为最好的选择是编写一个简单的转换函数,如下所示:

uint16_t colorToInt(color_t c)
{
    uint16_t ret = 0;
    ret |= c.blue;
    ret |= c.green << 5;
    ret |= c.red << 10;
    return ret;
}
这里是相反的情况:

color_t intToColor(uint16_t x)
{
    color_t ret = {
        .blue = 0 | x,
        .green = 0 | x >> 5,
        .red = 0 | x >> 10
    };
    return ret;
}

旁注:避免使用以
结尾的标识符\u t
。它们由POSIX标准保留。我还建议不要使用
typedef
s,除非您正在创建一个包含完全不透明对象的库。

我认为您最好的选择是编写一个简单的转换函数,如下所示:

uint16_t colorToInt(color_t c)
{
    uint16_t ret = 0;
    ret |= c.blue;
    ret |= c.green << 5;
    ret |= c.red << 10;
    return ret;
}
这里是相反的情况:

color_t intToColor(uint16_t x)
{
    color_t ret = {
        .blue = 0 | x,
        .green = 0 | x >> 5,
        .red = 0 | x >> 10
    };
    return ret;
}

旁注:避免使用以
结尾的标识符\u t
。它们由POSIX标准保留。我还建议不要使用
typedef
s,除非您正在创建一个包含完全不透明对象的库。

color\u t
uint16\u t
合并。请注意,该标准不保证位字段布局。我应该怎么做?对
color\u t
uint16\u t
进行
union
。请注意,该标准不保证位域布局。我该怎么做?我同意您的解决方案,但我正在寻找一种不同的方法。@Amateratis注意,该解决方案可能看起来过于复杂,但事实上它比
union
one更具可移植性。正如我前面提到的,bitfelds布局不受C标准的保证,而此代码在任何平台上都有一个完美定义的行为。我同意您的解决方案,但我一直在寻找一种不同的方法。@Amaterastis注意到此解决方案可能看起来过于复杂,但实际上它比
union
one更具可移植性。正如我前面提到的,bitfelds布局不受C标准的保证,而这段代码在任何平台上都有一个完美定义的行为。如果您提出这样的解决方案,您应该提到这依赖于实现定义的行为。这段代码是不可移植的。如果您提出这样的解决方案,您应该提到这依赖于实现定义的行为。此代码不可移植。