Использование массива символов в качестве массива длинных целых - PullRequest
1 голос
/ 14 января 2010

На моем AVR у меня есть массив символов, которые содержат информацию об интенсивности цвета в виде {R, G, B, x, R, G, B, x, ...} (x - неиспользуемый байт). Есть ли простой способ записать длинное целое (32-битное) в char myArray[4*LIGHTS], чтобы я мог легко написать число 0x00BBGGRR?

У меня грубая типизация, и я не знаю, как ее написать. Я предполагаю, просто сделать указатель на тип long long и установить его равным myArray, но тогда я не знаю, как произвольно сказать ему установить группу 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-бит?

Ответы [ 7 ]

5 голосов
/ 14 января 2010
typedef union {
    struct {
         uint8_t    red;
         uint8_t    green;
         uint8_t    blue;
         uint8_t    alpha;
    }          rgba;
    uint32_t   single;
} Color;

Color    colors[LIGHTS];

colors[0].single = WHITE;
colors[0].rgba.red -= 5;

ПРИМЕЧАНИЕ. В системе с прямым порядком байтов младший байт 4-байтового значения будет альфа-значением; тогда как это будет красным значением в системе с прямым порядком байтов.

2 голосов
/ 14 января 2010

Ваш код действителен. Вы можете использовать myRGBGroups как обычный массив, поэтому для доступа к 10-му пикселю вы можете использовать

myRGBGroups[9]
1 голос
/ 14 января 2010

Вам необходимо учитывать endianness из uint32_t на AVR, чтобы убедиться, что компоненты хранятся в правильном порядке (для последующей разыменования через массив myLights), если вы собираетесь сделать это. Быстрый Google, кажется, указывает, что AVR хранят данные в памяти с прямым порядком байтов, но другие регистры различаются по порядку байтов.

В любом случае, предполагая, что вы это сделали, вы можете разыменовать myRGBGroups, используя индексацию массива (где каждый индекс будет ссылаться на блок из 4 байтов). Итак, чтобы установить 10-ую группу, вы можете просто сделать myRGBGroups[ 9 ] = COLOR.

1 голос
/ 14 января 2010

Подумайте об использовании C union, где первое поле объединения - это int32, а второе - вектор из 4 * символов. Но не уверен, что это лучший способ для вас.

0 голосов
/ 21 февраля 2010

Вы можете выполнить что-то подобное, используя присвоение структуры - это решает проблему с порядком байтов:

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, скажем), то вы, скорее всего, не увидите какого-либо выигрыша в производительности от любой из этих технологий.

0 голосов
/ 15 января 2010

Объединение структуры и uint32_t - намного лучшая идея, чем создание uint8_t размера 4 * LIGHTS. Другой довольно распространенный способ сделать это - использовать макросы или встроенные функции, которые выполняют побитовую арифметику, необходимую для создания правильного 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);

В зависимости от вашего порядкового номера значения могут быть помещены в int в другом порядке. Этот метод распространен, потому что для более старых цветовых форматов 16bpp, таких как RGBA5551 или RGB565, более разумно думать о цветах с точки зрения побитовой арифметики, чем в единицах байтов.

0 голосов
/ 14 января 2010

, если можно использовать арифметику для myRGBgroup, например myRGBgroups ++ даст следующую группу, аналогично вы можете использовать операторы плюс, минус и т. Д. Эти операторы работают с использованием размеров шрифта, а не одного байта

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