#c #struct #assignment-operator
Вопрос:
Мне было интересно, есть ли более краткий способ назначить одну и ту же переменную нескольким членам одной и той же структуры?
В настоящее время мой код выглядит так:
image[i][j].rgbtBlue = average;
image[i][j].rgbtGreen = average;
image[i][j].rgbtRed = average;
Это просто кажется большим раскаянием. Я не хочу каким-либо образом изменять структуру, мне просто интересно, есть ли способ сделать приведенный выше код более аккуратным? Но в любом случае вот код для структуры.
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
ТИА
Комментарии:
1. Если вы хотите назначить все поля структуры, вы можете назначить всю структуру вместо отдельных полей. Или вы можете создать функцию или макрос препроцессора.
2. Я не уверен, что это аккуратнее (и не будет быстрее из-за атрибута packed), но вы могли бы использовать составной литерал :
image[i][j] = (RGBTRIPLE){average, average, average};
.3. еще одна возможность, вы могли бы
image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = average;
4. В дополнение к моему предыдущему использованию составного литерала обратите внимание, что инициализаторы расположены в том же порядке, что и структура, т. Е. BGR. Вы можете использовать макрос для построения составного литерала в порядке RGB , если это более удобно:
#define MK_RGB(r, g, b) ((RGBTRIPLE){.rgbtBlue = (b), .rgbtGreen = (g), .rgbtRed = (r)})
, затемimage[i][j] = MK_RGB(someR, someG, someB);
.
Ответ №1:
Вы можете создать структуру только для чтения, содержащую значения инициализации по умолчанию:
const RGBTRIPLE RGB_default =
{
.rgbtBlue = average,
.rgbtGreen = average,
.rgbtRed = average,
};
И затем:
RGBTRIPLE something[n];
for(size_t i=0; i<n; i )
{
something[i] = RGB_defau<
}
Комментарии:
1. Спасибо. Это не то решение, с которым я в конечном итоге согласился на этот раз, так как я действительно не хотел возиться со структурами, но, безусловно, что-то, что я мог бы рассмотреть в другой раз
Ответ №2:
Одним из способов было бы
image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = average;
Если вам надоело печатать « image[i][j]
«, и вы много делаете с ним в одном и том же фрагменте кода, вы можете настроить временную переменную:
RGBTRIPLE *trip = amp;image[i][j];
trip->rgbtBlue = trip->rgbtGreen = trip->rgbtRed = average;
Настройка временной переменной, подобной этой, имеет некоторые плюсы и минусы:
- Pro: это экономит ввод текста
- Кон: но сохранение набора текста на самом деле не является целью, вы вводите его только один раз
- Pro: это может быть проще для чтения
- Кон: если вы не будете осторожны (если
i
илиj
изменится, когда вы этого не ожидаете), это может привести к ошибкам
Комментарии:
1. Спасибо! Я нашел ваше первое решение, наиболее подходящее для моих нужд. Я довольно новичок в программировании, поэтому не хотел слишком сложного решения, и это единственный раз, когда мне это нужно в моем коде, чтобы он работал идеально.
Ответ №3:
(Поскольку все предлагают разные решения, я тоже упомяну свое!)
Один из вариантов-использовать составной литерал для хранения временного RGBTRIPLE
значения, заполненного нужными значениями. Поскольку кажется удобным указывать значения в порядке RGB, чтобы они соответствовали имени типа, можно определить некоторые удобные макросы для построения составного литерала:
#define MK_RGB(r, g, b) ((RGBTRIPLE){ .rgbtBlue = (b), .rgbtGreen = (g), .rgbtRed = (r) })
#define MK_GREY(g) MK_RGB(g, g, g)
Затем исходные строки кода:
image[i][j].rgbtBlue = average;
image[i][j].rgbtGreen = average;
image[i][j].rgbtRed = average;
Может быть изменен на:
image[i][j] = MK_RGB(average, average, average);
или:
image[i][j] = MK_GREY(average);
Примечание: Составные литералы были добавлены в C11. Чтобы соответствовать более старым стандартам C, MK_RGB
можно было бы изменить функцию, которая возвращает RGBTRIPLE
:
RGBTRIPLE MK_RGB(BYTE r, BYTE g, BYTE b)
{
RGBTRIPLE rgb;
rgb.rgbtRed = r;
rgb.rgbtGreen = g;
rgb.rgbtBlue = b;
return rgb;
}
Комментарии:
1. Спасибо. Так много разных вариантов! Я довольно новичок в программировании и не совсем уверен, что такое составной литерал (я уверен, что это не так сложно, и я скоро столкнусь с этим), но для этой проблемы я остановился на немного менее элегантном, но более простом варианте.
Ответ №4:
2 простых способа, которые я могу придумать с головы до ног:
- Используйте функцию:
т.е..
void RGBstructSet(RGBTRIPLE *lStruct,uint8_t value){
lStruct->rgbtBlue = value;
lStruct->rgbtGreen = value;
lStruct->rgbtRed = value;
}
И ваши вышеуказанные 3 строки будут затем заменены на:
structSet(amp;image[i][j], average);
- используйте memset, который гарантированно будет работать только с тех пор, как ваша структура «УПАКОВАНА», т. Е.
memset(amp;image[i][j],average,3)
1 имеет преимущество в том, что работает независимо от того, упакована ваша структура или нет, 2 немного проще для вас и более понятно, что происходит
Комментарии:
1. Спасибо. В какой-то момент я действительно рассматривал возможность использования функции, но, поскольку это единственный раз, когда я буду использовать этот код, казалось, что я создаю больше строк кода просто ради этого. Но если бы у меня было что-то, что нуждалось в этом решении для нескольких частей кода, то да, функция имеет больше смысла.