Перейти к содержанию
    

Использование глобальных переменных

Собрать все параметры в структуру (наверняка это уже сделано для удобства сохранения/чтения да и вообще для повышения читабельности кода). Передавать в редактор указатель на эту структуру. Можно создавать копию этой структуры, передавать в редактор указатель на копию и переписывать обратно из копии в основную структуру только после того, как пользователь подтвердит, что он действительно в своем уме.

 

Тоже хотел квакнуть, но это уже сделали.

Это промежуточный вариант к ООП. Каждый модуль как-бы "псевдо-клас" со своими данными в виде струкутуры, которая extern и видна глобально через

1 указатель. Позволяет сильно сэкономить на написании "extern".

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Позволяет сильно сэкономить на написании "extern".

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Народ, не поделитесь примерами?

примерно так:

bool cfg_editor::do_edit(bool from_last)
{
    // return true to edit field
    auto always            = [](cfg_cache &)     { return true; };
    auto dhcp_disabled     = [](cfg_cache & cfg) { return cfg->Localhost.DHCP_enabled == false; };


    struct
    {
        bool (*is_item_active)(cfg_cache &);
        cfg_editor_ui::result (*function)(cfg_editor *);
    } const Table[] =
    {
    #define HANDLER(edit_func, param_name, ...)  [](cfg_editor * editor) { return editor-> edit_func (param_name , editor->Cfg-> __VA_ARGS__); }
        { always,         HANDLER(edit_MAC,       "MAC address    ",                          Localhost.MAC_address) },
        { always,         HANDLER(choose_YN,      "DHCP enabled "  ,                          Localhost.DHCP_enabled) },
        { dhcp_disabled,  HANDLER(edit_IP,        "IP address     ",                          Localhost.IP_address.addr) },
        { dhcp_disabled,  HANDLER(edit_IP,        "Netmask        ",                          Localhost.Netmask.addr) },
        { dhcp_disabled,  HANDLER(edit_IP,        "Gateway        ",                          Localhost.Gateway.addr) },
#if LWIP_DNS
        { dhcp_enabled,   HANDLER(edit_IP,        "DNS1           ",                          Localhost.DNS[0].addr) },
        { dhcp_enabled,   HANDLER(edit_IP,        "DNS2           ",                          Localhost.DNS[1].addr) },
#endif
        { always,         HANDLER(edit,           "Hostname       ",                          Localhost.Hostname) },

        { always,         HANDLER(edit,           "Telnet port    ",                          Telnet.Port) },
        { always,         HANDLER(edit_password,  "Telnet password (space = disabled)",       Telnet.Password) },

        { always,         HANDLER(edit,           "Serial port baudrate   ",          Serial.Baudrate, 600, 115200) },
        .........
    };

    size_t const Last_index = sizeof(Table) / sizeof(Table[0]) - 1;
    size_t Index = from_last ? Last_index : 0;

    for(;;)
    {
        Console.new_line();
    Repeat:
        switch(Table[Index].function(this))
        {
        case result::CONSOLE_CLOSED:
        case result::TIMEOUT:
            return false;

        case result::ABORTED:
            return true;

        case result::KEY_UP:
            if(Index == 0)
            {
                Console.send('\r');
                goto Repeat;
            }
            while(--Index && !Table[Index].is_item_active(Cfg))
               ;
            break;

        case result::JUST_ENTER:
        case result::OK:
            if(Index == Last_index)
                return true;
            while(++Index < Last_index && !Table[Index].is_item_active(Cfg))
               ;

            if(!Table[Index].is_item_active(Cfg))   // if last item inactive
                return true;
            break;

        case result::KEY_DOWN:
            if(Index == Last_index)
            {
                Console.send('\r');
                goto Repeat;
            }
            while(++Index < Last_index && !Table[Index].is_item_active(Cfg))
               ;
            // last index inactive, go back to active
            if(Index == Last_index && !Table[Index].is_item_active(Cfg))
            {
                while(--Index && !Table[Index].is_item_active(Cfg))
                   ;
                Console.send('\r');
                goto Repeat;

            }
            break;
        }
    }
    return true;    // make eclipse parser happy
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

примерно так:

struct

{

bool (*is_item_active)(cfg_cache &);

cfg_editor_ui::result (*function)(cfg_editor *);

} const Table[]

 

Таблица const, но не static - живет на стеке и заполняется при каждом входе в функцию :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таблица const, но не static - живет на стеке и заполняется при каждом входе в функцию :)
Оп-па! Правда со static оно тоже в ОЗУ (до стандарта C++17 лямбды не являются constexpr), но уже не на стеке. Спасибо, упустил.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неправда. static позволяет не засорять глобальное пространство имён. Скажем, если в программе два десятка модулей, и в каждом - десяток своих переменных, то это уже 200 глобальных переменных. Кому нужен этот бардак?

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

Но чтобы следовать упомянутому ТС принципу "использование глобальных переменных нужно максимально минимизировать" перевода из static в глобальные недостаточно, нужно перевести эту переменную в параметры. Этот принцип никак не регламентирует количество глобальных переменных.

 

Было:

void func()

{

static int value =0;

//

модифицирующий код value;

}

 

Стало:

int value =0;

 

void func(int* value)

{

//

модифицирующий код value;

}

 

 

 

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Создаю библиотеку (lib) в Keil по исходникам из множества файлов.

Затем получившуюся библиотеку пристыковываю к другому проекту (главному).

 

При линковке выдаёт ошибку: найдены одинаковые имена в libfile.o и module.o

 

Исходные тексты программ не моего авторства, около 100 имён совпадает, так что переименовывать не вариант.

 

Попробуйте убедить его, что он сам себе хозяин и static значения не имеет ;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

примерно так:

У этого автора не так все легко с абстракциями, вряд ли вы ему помогли.

 

Нужно начинать с чего-нибудь попроще.

Вот, например, два датчика Холла, описанные в заголовочном файле для доступа снаружи

 

#define    HALLS_CHANNELS_QTY    2

typedef struct
{    int             position;
    unsigned char    cur;                //current_inputs;
    unsigned char    prev;            //previous_inputs
    unsigned char    prev_prev;        //before previous inputs
    unsigned char    init;
}    hall_type;

extern hall_type hall[HALLS_CHANNELS_QTY];
extern hall_type old_hall[HALLS_CHANNELS_QTY];

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хочу узнать мнение насчет использования глобальных переменных. Спрашиваю вот почему: неоднократно слышал, что использование глобальных переменных нужно максимально минимизировать. Откуда пошло это? В данный момент пишу проект. Свои проекты всегда стараюсь разделить на модули. static переменные. использование в других модулях посредством set_value (); get_value ();. Но в нынешнем проекте у меня много параметров. И если честно, я заколебался на каждую переменную писать свои функции установки и получения переменных. Хочу вывести переменные из static в глобальные.

Ваши за и против.

Не один из принципов нельзя возводить в абсолют.

Если нельзя, но очень хочется и это сильно упрощает жизнь - то можно.

Вон про GOTO тоже написано, что "правильные пасаны" GoTO не используют.

А тем не менее ИМЕННО GOTO в ряде случаев упрощает код и делает его более читабельным

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну бардак все-таки не хаос. Переменные видимы в определенном порядке и избыточное количество не критично: пусть лучше уж валяется в глобальном списке, чем тратить на нее семиразовое нажатие клавиш.

 

У вас очень трепетное отношение к нажатию клавиш :) Опять же, имена глобальных переменных обычно должны быть длинными и осмысленными, часто это больше 7 символов ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте убедить его, что он сам себе хозяин и static значения не имеет ;)

Как раз в приведенном примере из соседней ветки static значения не имеет:

static имеет целью сделать переменную недоступной извне, что совершенно не подходит топикстартеру.

Там конфликт имен в чистом виде.

 

У вас очень трепетное отношение к нажатию клавиш :) Опять же, имена глобальных переменных обычно должны быть длинными и осмысленными, часто это больше 7 символов ;)

7-кратное нажатие - это написание "static"+пробел перед глобальными переменными, которые желательно сделать недоступными вне файла.

В случае "сам себе хозяин" без них можно обойтись.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7-кратное нажатие - это написание "static"+пробел перед глобальными переменными, которые желательно сделать недоступными вне файла.

В случае "сам себе хозяин" без них можно обойтись.

 

Я как раз про нажатия и говорю. Глобальная переменная - это тип, название и комментарий, причем название должно быть достаточно длинным. Т.е. несколько десятков символов точно. На этом фоне экономия 7 символов - это ни о чем. Можно конечно давать имена вроде xz42 и комментарии не писать :maniac:

 

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

 

Поэтому рекомендация не использовать static из-за затрат на его написание смотрится странновато :) Но если экономить символы, то ничто не мешает написать #define S static - это минус 5 нажатий ;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поэтому рекомендация не использовать static из-за затрат на его написание смотрится странновато :)

 

Как раз ровно наоборот: я одобряю решение топикстартера затратить лишние нажатия клавиш на удаление уже написанного static.

Что бы не писать для доступа к переменным функции-обертки (или макросы). Для единоличника считаю это допустимым и вполне разумным.

С небольшой поправкой: для переменных, которые могут изменить свою структуру в будущем, не полениться и написать доступ через обертки.

 

 

Но если экономить символы, то ничто не мешает написать #define S static - это минус 5 нажатий ;)

Не, такой хоккей нам не нужен.

Конечно, это дело личных предпочтений, но как по мне "S" вместо static смотрится еще хуже переменной xz42.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...