C 从内存中提取n个字节

C 从内存中提取n个字节,c,C,假设我有一个指向图像数据的指针,它有3个通道(RGB),每个通道8位,我想显示像#000000这样的像素值,这是一个24位的数字。数据以RGB RGB RGB RGB格式存储。。。所以我真的需要读取前三个字节 typedef unsigned char uchar; uchar* data = get_image_data_somehow(); 也许这比我想象的要容易,但如果我有四个字节,我可以做类似的事情 uint32 value = *((uint32*) data); printf("V

假设我有一个指向图像数据的指针,它有3个通道(RGB),每个通道8位,我想显示像#000000这样的像素值,这是一个24位的数字。数据以RGB RGB RGB RGB格式存储。。。所以我真的需要读取前三个字节

typedef unsigned char uchar;
uchar* data = get_image_data_somehow();
也许这比我想象的要容易,但如果我有四个字节,我可以做类似的事情

uint32 value = *((uint32*) data);
printf("Value is %x", value);

怎么做?原则上,我需要32位的1,并用0填充前导的8位。

您可以通过8位右移来实现这一点

uint32_t value = *((uint32_t*) data) >> 8;
printf("Value is %0X", value);
示例中,
数据
是两个像素的值
#1177ff

data       = 11 77 ff 11 77 ff
value      = 11 77 ff 11
value >> 8 = 00 11 77 ff

你可以右移8位来达到这个目的

uint32_t value = *((uint32_t*) data) >> 8;
printf("Value is %0X", value);
示例中,
数据
是两个像素的值
#1177ff

data       = 11 77 ff 11 77 ff
value      = 11 77 ff 11
value >> 8 = 00 11 77 ff
(假设你在一台小小的Endian机器上)

(假设您使用的是小型Endian机器)

您可以使用来提取数据,或将其部门化

它看起来像这样:

union myRGB {
    unsigned int data;
    struct RGB
    {
       unsigned char a, b, g, r;
    }
}

myRGB value = *((uint32*) data);

printf("R Value is %x", value.RGB.a);

您可以使用提取数据,或将其部门化

它看起来像这样:

union myRGB {
    unsigned int data;
    struct RGB
    {
       unsigned char a, b, g, r;
    }
}

myRGB value = *((uint32*) data);

printf("R Value is %x", value.RGB.a);


乐是怎么回事?正如作者所提到的,有一个严格的字节顺序。因此,如果源(三个字节)和目标(四个字节)的大小不同,memcpy将对齐右侧的三个字节?@AndrejsCainikovs是的,没有@沃尔-奥-马特右图;目标中其他字节的内容不变(因此,如果未知,则清除它更安全)。此外,
memcpy
读取的内存不会超过需要,而复制uint32将进行4字节读取。不过你的情况没什么好担心的。你怎么了?正如作者所提到的,有一个严格的字节顺序。因此,如果源(三个字节)和目标(四个字节)的大小不同,memcpy将对齐右侧的三个字节?@AndrejsCainikovs是的,没有@沃尔-奥-马特右图;目标中其他字节的内容不变(因此,如果未知,则清除它更安全)。此外,
memcpy
读取的内存不会超过需要,而复制uint32将进行4字节读取。不过,在您的情况下没有什么可担心的。
%0X
看起来会更好+1'd.@AdamZalcman:仅举一个例子,说明数据类型的大小。例如,GLib提供了相应的typedef,比如guint32,我认为仅仅使用简单的“int”可能会因机器而异。@AdamZalcman-OP的代码中有。我猜他在什么地方打过。如果您不喜欢
uint32
,请随意替换
uint32\u t
无符号int
,尽管您碰巧拥有的任何32位无符号整数类型都可以完成此任务。@AdamZalcman-啊,是的,忘记了那个类型。我想
int
是因为整个
int
/
long int
/
long
交易而固定的。我将更新原始代码以使用
uint32\u t
。。。获取第一个字节(无符号字符)将返回“0x2A”,这是我所期望的。但是使用您建议的方法(不移位)获取前四个字节会返回“0x27262a”,这是我期望的镜像,第一个0x27是第二个像素的红色值。这和小恩迪安等有关系吗?移位后,返回0x27(而不是预期的0x2A2627)
%0X
看起来更好+1'd.@AdamZalcman:仅举一个例子,说明数据类型的大小。例如,GLib提供了相应的typedef,比如guint32,我认为仅仅使用简单的“int”可能会因机器而异。@AdamZalcman-OP的代码中有。我猜他在什么地方打过。如果您不喜欢
uint32
,请随意替换
uint32\u t
无符号int
,尽管您碰巧拥有的任何32位无符号整数类型都可以完成此任务。@AdamZalcman-啊,是的,忘记了那个类型。我想
int
是因为整个
int
/
long int
/
long
交易而固定的。我将更新原始代码以使用
uint32\u t
。。。获取第一个字节(无符号字符)将返回“0x2A”,这是我所期望的。但是使用您建议的方法(不移位)获取前四个字节会返回“0x27262a”,这是我期望的镜像,第一个0x27是第二个像素的红色值。这和小恩迪安等有关系吗?移位后返回0x27(而不是预期的0x2A2627),我也会在这里设置+1,但我认为您的代码编写得不好,并且有一个错误。@AndrejsCainikovs可能有一个错误,只是为概念起草了一个错误,您能指出错误吗?嗯,我想您已经修复了一些问题。我在这里考虑的是endianness,虽然它不是真正的错误,但在某些架构上可能不起作用。检查多项式答案下的注释。我也会在这里设置+1,但我认为您的代码写得不好,并且有一个错误。@AndrejsCainikovs可能有一个错误,只是为概念起草了它,您能指出错误吗?嗯,我想您已经修复了一些东西。我在这里考虑的是endianness,虽然它不是真正的错误,但在某些架构上可能不起作用。检查多项式答案下的注释。