Использование псевдонимов вместо имени переменной

Добрый день!
Суть вопроса: имеется некая процедура TEST, аргументом которой является число k. В зависимости от значения k нужно выполнять много одних и тех же действий, но с различными глобальными переменными (для примера: a, b, c).

Как я оформляю это сейчас:

void TEST (byte k) {
  switch (k) {
    case 1: a = 0; a = 1; a = 2; a = 3; break; //действия указаны образно, для примера
    case 2: b = 0; b = 1; b = 2; b = 3; break;
    case 3: c = 0; c = 1; c = 2; c = 3; break;
  }
}

Вопрос: можно ли создать какой-то псевдоним (pse*), присваивать ему имена переменных внутри кода и использовать его в последствии вместо имен переменных? Т.е. что я хотел бы получить на выходе:

void TEST (byte k) {
  switch (k) {
    case 1: pse* = a; break;
    case 2: pse* = b; break;
    case 3: pse* = c; break;
  }
  pse = 0; pse = 1; pse = 2; pse = 3; //вот тут надо чтобы в зависимости от значения k выполнялись действия с переменными a b или c
}

P.S. если что, можете просто подсказать как это правильно называется, а нагуглить я сам нагуглю. Просто хз как это правильно называть, чтоб запрос сформировать
PP. S. Пример обобщенный. Есть конечно и другие способы оптимизировать мой код в реальной задаче, но такой, в случае если это возможно, импонирует мне больше всего.
PPP. S. Почему бы просто не использовать доп. переменную, а не выдумывать псевдонимы? Потому что в реальной задаче переменные a b c - это массивы. Т.е. там надо создавать еще один массив той же разномерности - не хочу, в целях экономии памяти. А так можно было бы обойтись без лишнего массива

Вызывайте из Case свои функции.

вы бы какой-то реальный пример привели, а то вот это тяжелым бредом попахивает:

1 лайк

Выполнять действия внутри процедуры с глобальными переменными - это гавнокод. В правильном коде процедура должна быть самодостаточным блоком кода. То есть работать только с парметрами вызова и локальными переменными.
Передавайте свои переменные внутрь процедуры как параметры - это и будет то, что вы называете “псевдонимами”

И снова здравствуйте, мой дорогой и уважаемый друг :slight_smile: снова мы с вами встретились на просторах данного форума. Как помните, я больше в машинах разбираюсь, чем в программировании, поэтому не сердчайте. :grinning:
Я намеренно не указывал конкретный пример, так как будет 100 советов как оптимизировать код иначе, а меня в целях образования интересует возможность реализации именно этого метода

хотите сказать, что я забыл включить вас в мой игнор-лист? сию минуту поправим…

Скорее наоборот, вы из тех, кто ко мне наиболее адекватно отсился относительно других обитателей форума, но можете и в игнор сунуть, ежели вам там угодно)
Если что это я вам пару лет назад TLCшки отправлял на проверку, а в прошлом году устроил срач в теме про соединение контакта BAT DS1307 с пином 3v3 ардуины)

А кто вас заставляет?

void pse(byte x)
{
  x = 0;
  x = 1;
  x = 2;
  x = 3; // действия указаны образно, для примера
}

void TEST(byte k)
{
  switch (k)
  {
  case 1:
    pse(a);
    break; 
  case 2:
    pse(b);
    break;
  case 3:
    pse(c);
    break;
  }
}
1 лайк

Хорошо, согласен, это один из способов оптимизации и тут он сработает, согласен. Но пример я дал максимально упрощенный. Вопрос про “псевдонимы” я задал на 50% для практического применения и на 50% из образовательных соображений. Внутренний голос подсказывает, что С как-то позволяет использовать псевдонимы, присваивая им имена переменных в теле кода, а потом использовать псевдоним вместо имени переменной.
Окей, открою ящик пандоры и распишу реальную задачу, но сейчас посыпется сотня альтернативных вариантов оптимизации кода, но таким образом я закрою вопрос только на 50% - практическую часть, а теоретическая останется открытой.

Реальный проект

Ой!

Проект банально простой: часы на адресных светодиодах, из которых сформированы 4 / 6 семисегментных разрядов (с секундами и без). Каждый разряд - это массив из 7ми светодиодов. В программе они определяются объектами библиотеки FastLED и представляют из себя 4 / 6 массива по 7 элементов:
LED_H[7] - первый разряд (десятки часов)
LED_h[7] - второй разряд (единицы часов)
LED_M[7]
LED_m[7]
LED_S[7]
LED_s[7]

Я создал процедуру DRAW с аргументами P и N, где P - разряд, а N - выводимая цифра. Соответственно вызов в теле программы DRAW(1,2) - должен нарисовать в первый разряд цифру “2”.

Я реализовал это самым тупым способом:

Внимание, может вызывать кровоточивость глаз
void DRAW(byte P, byte N) {
  switch(N) {
    case 0: if (P==1) {
              // Рисуем 0
              LED_H[0] = CRGB(255,0,0) //Включает 1-ый светодиод красным цветом
              LED_H[1] = CRGB(255,0,0) //Включает 2-ой светодиод красным цветом
              LED_H[2] = CRGB(255,0,0) 
              LED_H[3] = CRGB(255,0,0) 
              LED_H[4] = CRGB(255,0,0) 
              LED_H[5] = CRGB(255,0,0) 
              LED_H[6] = CRGB(0,0,0) //Выключает 7-ой светодиод
            }

            if (P==2) {
              LED_h[0] = CRGB(255,0,0) //Включает 1-ый светодиод красным цветом
              LED_h[1] = CRGB(255,0,0) //Включает 2-ой светодиод красным цветом
              LED_h[2] = CRGB(255,0,0) 
              LED_h[3] = CRGB(255,0,0) 
              LED_h[4] = CRGB(255,0,0) 
              LED_h[5] = CRGB(255,0,0) 
              LED_h[6] = CRGB(0,0,0) //Выключает 7-ой светодиод
            }

            if (P==3) {
              LED_M[0] = CRGB(255,0,0) //Включает 1-ый светодиод красным цветом
              LED_M[1] = CRGB(255,0,0) //Включает 2-ой светодиод красным цветом
              LED_M[2] = CRGB(255,0,0) 
              LED_M[3] = CRGB(255,0,0) 
              LED_M[4] = CRGB(255,0,0) 
              LED_M[5] = CRGB(255,0,0) 
              LED_M[6] = CRGB(0,0,0) //Выключает 7-ой светодиод
            }
            
            if (P==4) {
              LED_m[0] = CRGB(255,0,0) //Включает 1-ый светодиод красным цветом
              LED_m[1] = CRGB(255,0,0) //Включает 2-ой светодиод красным цветом
              LED_m[2] = CRGB(255,0,0) 
              LED_m[3] = CRGB(255,0,0) 
              LED_m[4] = CRGB(255,0,0) 
              LED_m[5] = CRGB(255,0,0) 
              LED_m[6] = CRGB(0,0,0) //Выключает 7-ой светодиод
            }
    break;
  }

…и так далее, ещё для массивов LED_S и LED_s и потом ещё для остальных цифр от 1 до 9.
Т.е. я использовал case для выводимых цифр N, а внутри кейса в зависимости от значения аргумента P (через if, чтоб не делать вложенные кейсы) включаю нужные светодиоды в разных массивах.
Понимаю, что решение не самое оптимальное, но только не надо пожалуйста говорить, что уже есть куча готовых решений. Я не люблю ими пользоваться, так как интересней самому, да и разбирать в этом коде мне будет потом проще, потому что сам же его и писал )
Знаю несколько способов по оптимизации этого г***окода: с использование массива-маски или даже просто битовой маски, но в голову закралась идея с псевдонимом, что было бы не плохо реализовать это примерно так:

Код мечты
void DRAW(byte P, byte N) {
  switch(N) {
    case 0: if (P==1) pse* = LED_H;
            if (P==2) pse* = LED_h;
            if (P==3) pse* = LED_M;
            if (P==4) pse* = LED_m;

            pse*[0] = CRGB(255,0,0) //Включает 1-ый светодиод красным цветом
            pse*[1] = CRGB(255,0,0) //Включает 2-ой светодиод красным цветом
            pse*[2] = CRGB(255,0,0) 
            pse*[3] = CRGB(255,0,0) 
            pse*[4] = CRGB(255,0,0) 
            pse*[5] = CRGB(255,0,0) 
            pse*[6] = CRGB(0,0,0) //Выключает 7-ой светодиод
    break;

   case 1: ...
  }
}

Может я и дохрена хочу и так нельзя - если таких “псевдонимов” не существует, то вопрос снят ) А оптимизировать код иными путями думаю я тоже смогу, немного посидев и подумав. Просто пока не было времени на то самое “посидеть и вдумчиво подумать”, а опыта чтоб сходу написать оптимально, как понимаете, не много )

Читайте учебники, не слушайте голоса. В частности, обратите внимание на раздел про указатели и ссылки

2 лайка

Ок
Они до сих пор у меня в коробке лежат и мне до сих пор стыдно, что не смог их завести.

так можно, но сложно. Если хотите подробнее - покажите как описаны массивы светодиодов.
Значительно проще описать все шесть массивов как единую ленту и выводить цифры в нужную позицию по смещению диода

Это реально тупой способ. Зачем изобретать велосипед?
Один сегмент - это один байт, в котором нулями и единицами закодировано, какие светодиоды должны светиться. Вот так это делается

//
//      A
//     ---
//  F |   | B
//     -G-
//  E |   | C
//     ---
//      D
// Здесь A .. G - соответствующие светодиоды

const uint8_t digitToSegment[] = {
 // XGFEDCBA
  0b00111111,    // 0
  0b00000110,    // 1
  0b01011011,    // 2
  0b01001111,    // 3
  0b01100110,    // 4
  0b01101101,    // 5
  0b01111101,    // 6
  0b00000111,    // 7
  0b01111111,    // 8
  0b01101111,    // 9
  0b01110111,    // A
  0b01111100,    // b
  0b00111001,    // C
  0b01011110,    // d
  0b01111001,    // E
  0b01110001     // F
  };

Т.е. один массив, в котором закодированы все символы от 1 до F

3 лайка

Да, этот вариант у меня отложен в голове как “запасной”, он код конечно ужмет, но потребует ввода доп. переменной-массива.

Это основной способ работы с семисегментными индикаторами. Возьмите любую библиотеку да хоть для TM1637 и изучите. Не изобретайте велосипед. А если уж совсем неймется - ниипите людям моск, разгребайте самостоятельно :sweat_smile:

1 лайк

Ну там микрухи всетаки неисправные скорее, в том нет вашей вины, так что нечего стыдится.
Что до массивов - тоже размышлял эту сторону, но разные разряды подключены к разным пинам ардуино (D2 D3 D4 D5), а при создании объекта там указывается пин, к которому подключена линейка светодиодов. Я в недра библиотеки не лез, для меня это темный лес до небес, я просто нашел как создавать ленты в программе и как их включать)

Можно конечно изменить аппаратную часть и реализовать все светодиоды как одну цепочку из 28 светодиодов (а не 4 по 7, как у меня) и сделать один массив и запрограммировать сдвиги для каждого разряда, но рука взяла почему-то 4 по 7… Возможно в будущем переделаю на 1 х 28

насколько я помню, в Фастледе такие отдельные цепочки светодиодов, подключенные к разным пинам - можно описать как целую ленту.
Но в принципе, можно сделать на отдельных массивах с использованием ссылок. Только вывод на ленту хорошо бы переписать, как @v258 советует, а то от этих одинаковых кейсов противно становится

1 лайк

Ну одинаковые кейсы в процессе работы часов никто не видит, а лишний массив 7 байт схавает :sweat_smile:
На самом деле завтра переделаю на массив - маску, на работе в свободное время просто этим занимаюсь, а сегодня не успел)

А что значит “на отдельных массивах с использованием ссылок”?

А что, памяти-то последние 7 байт осталось?

2 лайка

как в вашем “коде мечты”