我可以创建适用于不同字节序的颜色结构吗?

Can I create color struct that works on different endians?

提问人:Buğrahan Özcan 提问时间:11/17/2023 更新时间:11/17/2023 访问量:80

问:

我正在尝试创建一个联合来同时存储我的颜色值,逐个通道和 4 字节值。但是我对频道的顺序有问题。不同的字节序机器给出不同的值。有没有办法创建此结构的字节序证明版本,或者当不同的字节序更适合这项工作时使用不同的结构?我想将结构和联合用于教育目的。我正在试验,想了解 C 结构可以做什么和不能做什么。

typedef union u_color
{
    struct
    {
        unsigned char   blue;
        unsigned char   green;
        unsigned char   red;
        unsigned char   alpha;
    };
    unsigned int    value;
}   t_color;
c 结构 颜色 字节序 并集

评论

0赞 pmacfarlane 11/17/2023
听起来有点像 x/y 问题。是的,你是对的,当你访问该字段时,字节序会有所不同。如果你想在访问时交换字节序,你需要求助于宏黑客。value
0赞 pmacfarlane 11/17/2023
目前还不清楚“此结构的字节序证明版本”是什么意思。首先,您似乎假设 an 是 4 个字节,但情况可能并非总是如此。而且您似乎假设 32 位值中的字节顺序是某种顺序的。这个问题很奇怪。unsigned int
2赞 Eric Postpischil 11/17/2023
@pmacfarlane:回复“不太清楚”此结构的字节序证明版本“是什么意思”:这意味着他们希望成员始终对应于 、对应于 16-23、对应于 8-15 和对应于 0-7 的位 24-31。alphavalueredgreenblue
2赞 Eric Postpischil 11/17/2023
如果您使用的是 Clang 或 GCC,则可以用于测试字节序并选择按一种或另一种顺序列出成员的代码。这并不是所有 C 编译器都可移植的。但是,应该避免或小心控制这样的污垢。#if __LITTLE_ENDIAN__
1赞 Ted Lyngmo 11/17/2023
信息如何在不同字节序的机器之间传输?如果它保存在文件中,则需要就规则等的字节序达成一致。

答:

2赞 gulpr 11/17/2023 #1

如果您只想将其用于获取和设置(或从 ) 获取颜色,则(如果您使用最新的 gcc 系列编译器)valuevalue

typedef union u_color
{
  #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    struct
    {
        uint8_t   blue;
        uint8_t   green;
        uint8_t   red;
        uint8_t   alpha;
    };
  #else
    struct
    {
        uint8_t   alpha;
        uint8_t   red;
        uint8_t   green;
        uint8_t   blue;
    };
  #endif
    uint32_t    value;
}   t_color;

但是,对于表示真实屏幕数据结构的定义数组,您需要使用一个预定义的结构布局。

int main(void)
{
    t_color x = {.blue = 0x11, .green = 0x22, .red = 0x33, .alpha = 0x44};
    printf("%"PRIx32"\n", x.value);
}

尽管字节序,但始终会打印0x11223344。

评论

1赞 gulpr 11/17/2023
@TedLyngmo,我将为 PDP11 :)添加额外的检查。问题在于找到支持这些预定义宏的 gcc 版本:)
1赞 chux - Reinstate Monica 11/17/2023
@TedLyngmo 从 VT52 开始,您有 1 和 0。我的第一个键盘必须使用“i”和“O”。示例。;-)
1赞 chux - Reinstate Monica 11/17/2023
@TedLyngmo我仍然把我的名字写在石板上,但也在算盘上自学平方根。啊,体验技术变化的乐趣。
1赞 Ted Lyngmo 11/17/2023
@chux-恢复莫妮卡.“..你试着告诉今天的年轻人......他们不会相信你”。
1赞 Lundin 11/17/2023
据推测,我们很快就能用 C23 stdbit.h 在标准 C 中做到这一点。 等。不过,我认为还没有任何编译器支持这一点。__STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__
1赞 chux - Reinstate Monica 11/17/2023 #2

尽管可以根据字节序对 color/alpha 成员进行重新排序,但在读取和写入图形文件时,红色、绿色、蓝色的顺序是常态。我建议留下来。

代码一次可以存储 4 个字节,其中 a 为 r,g,b,a,而不是 .structunsigned

像素颜色不是 的好例子。union/struct

使用类型比在试验 s 时使用类型更好。(u)intN_tunsignedunion

评论

0赞 Buğrahan Özcan 11/19/2023
感谢您的帮助。我正在尝试和试验结构和联合。你能解释为什么 (u)intN_t 比无符号值更好吗?
1赞 chux - Reinstate Monica 11/19/2023
图形文件格式通常具有指定的位宽,因此可以与 匹配。此外,某些图形数据操作是特定于位宽的。 具有最小位宽要求,但实际宽度可能因实现而异。(u)intN_tint, long, ...
1赞 Lundin 11/17/2023 #3

KISS 解决方案只是简单地删除联合和值成员,然后始终通过函数获取值。100%便携:

#include <stdint.h>

typedef struct
{
  uint8_t blue;
  uint8_t green;
  uint8_t red;
  uint8_t alpha;
} t_color;

uint32_t t_color_value (const t_color* col)
{
  return ( ((uint32_t)col->blue  << 24) |
           ((uint32_t)col->green << 16) |
           ((uint32_t)col->red   <<  8) |
           ((uint32_t)col->alpha <<  0) );
}

int main (void)
{
  t_color col = { .blue=0x11, .green=0x22, .red=0x33, .alpha=0x44};
}

现在总是以最高有效字节结束,无论字节序如何。这是因为移位运算符与字节序无关(与联合或 memcpy 等不同)。blueuint32_t

评论

0赞 Buğrahan Özcan 11/19/2023
感谢您的帮助,但这个问题不仅仅是解决问题。我正在尝试学习如何使用结构、联合和预处理器,以及我有多大的灵活性。
1赞 Lundin 11/20/2023
@BuğrahanÖzcan 其中一部分是要意识到他们什么时候做不好,即在表示内存映射和数据协议时。一致性和对齐性通常会使依赖于结构/联合的代码不可移植。