C 将字符数组用作长整数数组

C 将字符数组用作长整数数组,c,arrays,avr,unions,avr-gcc,C,Arrays,Avr,Unions,Avr Gcc,在我的AVR上,我有一个字符数组,它以{R,G,B,x,R,G,B,x,…}(x是一个未使用的字节)的形式保存颜色强度信息。有没有简单的方法可以将长整数(32位)写入char myArray[4*LIGHTS]以便轻松地写入0x00BBGGRR数字 我的打字很粗糙,我不知道怎么写。我猜只要做一个指向长int类型的指针,并将其设置为等于myArray,但我不知道如何任意告诉它将group x设置为myColor uint8_t myLights[4*LIGHTS]; uint32_t *myRGB

在我的AVR上,我有一个字符数组,它以{R,G,B,x,R,G,B,x,…}(x是一个未使用的字节)的形式保存颜色强度信息。有没有简单的方法可以将长整数(32位)写入
char myArray[4*LIGHTS]
以便轻松地写入0x00BBGGRR数字

我的打字很粗糙,我不知道怎么写。我猜只要做一个指向长int类型的指针,并将其设置为等于myArray,但我不知道如何任意告诉它将group x设置为myColor

uint8_t myLights[4*LIGHTS];
uint32_t *myRGBGroups = myLights; // ?

*myRGBGroups = WHITE; // sets the first 4 bytes to WHITE
                      // ...but how to set the 10th group?

编辑:我不确定类型转换是否是正确的术语,因为我认为如果它只是将32位数字截断为8位会是正确的?

考虑使用C并集,其中并集的第一个字段是int32,第二个字段是4*字符的向量。但是,不确定这是否是最好的方法。

考虑使用C并集,其中并集的第一个字段是int32,第二个字段是4*个字符的向量。但是,不确定这是否是您的最佳方式。

如果要执行此操作,您需要说明AVR上的
uint32\t
,以确保组件以正确的顺序存储(以便以后通过
myLights
阵列取消引用)。一个快速的Google似乎表明AVR在内存中存储数据的方式是小端,但其他寄存器的端数不同


无论如何,假设您已经这样做了,您可以使用数组索引(其中每个索引将引用一个4字节的块)取消对
myRGBGroups
的引用。因此,要设置第10组,您只需执行
myRGBGroups[9]=COLOR

您需要考虑AVR上的
uint32\u t
,以确保组件以正确的顺序存储(以便以后通过
myLights
数组取消引用)。一个快速的Google似乎表明AVR在内存中存储数据的方式是小端,但其他寄存器的端数不同


无论如何,假设您已经这样做了,您可以使用数组索引(其中每个索引将引用一个4字节的块)取消对
myRGBGroups
的引用。因此,要设置第10个组,您只需执行
myRGBGroups[9]=COLOR

如果可以在myRGBGroups上使用算术,例如myRGBGroups++将给出下一个组,同样可以使用加号、减号等运算符。这些运算符使用类型大小而不是单字节进行操作

myRGBgroups[10] // access group as int
((uint8_t*)(myRGBgroups + 10)) // access group as uint8 array

如果可以在myRGBgroup上使用算术,例如myRGBgroups++将给出下一个组,同样可以使用加号、减号等运算符。这些运算符使用类型大小而不是单字节进行操作

myRGBgroups[10] // access group as int
((uint8_t*)(myRGBgroups + 10)) // access group as uint8 array
注:在小尾端系统上,4字节值的低位字节将是alpha值;而它将是大端系统上的红色值


注:在小尾端系统上,4字节值的低位字节将是alpha值;而它将是big-endian系统上的红色值。

您的代码完全有效。您可以使用myRGBGroups作为常规数组,以便访问第10个像素

myRGBGroups[9]

你的代码完全有效。您可以使用myRGBGroups作为常规数组,以便访问第10个像素

myRGBGroups[9]

将结构和uint32_t结合起来比制作尺寸为4*的uint8_t好得多。另一种相当常见的方法是使用宏或内联函数,这些宏或内联函数执行创建正确uint32\t所需的位运算:

#define MAKE_RGBA32(r,g,b,a) (uint32_t)(((r)<<24)|((g)<<16)|((b)<<8)|(a))
uint32_t colors[NUM_COLORS];
colors[i] = MAKE_RGBA32(255,255,255,255);

#define MAKE_RGBA32(r,g,b,a)(uint32_t)((r)结构和uint32_t的并集比生成大小为4*的uint8_t好得多。另一种相当常见的方法是使用宏或内联函数,这些宏或内联函数执行创建正确uint32_t所需的位运算:

#define MAKE_RGBA32(r,g,b,a) (uint32_t)(((r)<<24)|((g)<<16)|((b)<<8)|(a))
uint32_t colors[NUM_COLORS];
colors[i] = MAKE_RGBA32(255,255,255,255);

#定义MAKE_RGBA32(r,g,b,a)(uint32_t)((r)您可以使用结构赋值执行类似的操作-这解决了endian问题:

typedef struct Color {
    unsigned char r, g, b, a;
} Color;

const Color WHITE   = {0xff, 0xff, 0xff, 0};
const Color RED     = {0xff, 0, 0, 0};
const Color GREEN   = {0, 0xff, 0, 0};

Color colors[] = {WHITE, RED};
Color c;

colors[1] = GREEN;
c = colors[1];
但是,标准中没有定义比较,您不能使用
c==GREEN
,也不能在赋值中使用
{}
快捷方式(仅初始化),因此
c={0,0,0,0}
将失败


还请记住,如果是8位AVR(与AVR32相反),则很可能不会从这两种技术中看到任何性能优势。

您可以使用结构赋值执行类似的操作-这解决了endian问题:

typedef struct Color {
    unsigned char r, g, b, a;
} Color;

const Color WHITE   = {0xff, 0xff, 0xff, 0};
const Color RED     = {0xff, 0, 0, 0};
const Color GREEN   = {0, 0xff, 0, 0};

Color colors[] = {WHITE, RED};
Color c;

colors[1] = GREEN;
c = colors[1];
但是,标准中没有定义比较,您不能使用
c==GREEN
,也不能在赋值中使用
{}
快捷方式(仅初始化),因此
c={0,0,0,0}
将失败


还请记住,如果是8位AVR(与AVR32相反),则,那么您很可能看不到这两种技术对性能的任何好处。

这不会使我的内存需求增加一倍吗?我的8位AVR在空间和速度上都有相当大的限制,而且编译器似乎喜欢将我的强度值按顺序排列,以便在将数据中继到4通道灯光控制器时生成更小/更快的代码。不,联合使用所有字段,并对所有字段使用相同的块内存。因此,对其中一个字段的任何更改都将影响所有其他字段,因为它们从相同的内存地址读取。这也意味着添加的int32将从您当前从中读取单个RGBA值的同一块内存中读取m、 这不会使我的内存需求增加一倍吗?我的8位AVR在空间和速度上都有相当大的限制,而且编译器似乎喜欢让我的强度值按顺序排列,这样当它将数据中继到4通道灯光控制器时,它可以生成更小/更快的代码。不,一个联合会占用所有字段,并使用相同的块内存来处理所有数据m、 因此,对其中一个字段的任何更改都将影响所有其他字段,因为它们从相同的内存地址读取。这也意味着添加的int32将从当前从中读取单个RGBA值的同一块内存中读取。当然,union中的union没有任何意义。