Как присвоить одно и то же значение нескольким элементам структуры в C

#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 простых способа, которые я могу придумать с головы до ног:

  1. Используйте функцию:

т.е..

 void RGBstructSet(RGBTRIPLE *lStruct,uint8_t value){
lStruct->rgbtBlue = value;
lStruct->rgbtGreen = value;
lStruct->rgbtRed = value;
}
 

И ваши вышеуказанные 3 строки будут затем заменены на:

 structSet(amp;image[i][j], average);
 
  1. используйте memset, который гарантированно будет работать только с тех пор, как ваша структура «УПАКОВАНА», т. Е.
      memset(amp;image[i][j],average,3)
     

1 имеет преимущество в том, что работает независимо от того, упакована ваша структура или нет, 2 немного проще для вас и более понятно, что происходит

Комментарии:

1. Спасибо. В какой-то момент я действительно рассматривал возможность использования функции, но, поскольку это единственный раз, когда я буду использовать этот код, казалось, что я создаю больше строк кода просто ради этого. Но если бы у меня было что-то, что нуждалось в этом решении для нескольких частей кода, то да, функция имеет больше смысла.