Jump to content

    

Статические переменные в функции.

В последнее время увлекся использованием статических переменных в функции. Очень удобно - повышается переносимость функции из проекта в проект, повышается читаемость функции - видишь какими переменными она оперирует.

Но я как то не встречал проектов изобилующих статическими переменными в функции. Есть какие то подводные камни?

Edited by jenya7

Share this post


Link to post
Share on other sites
2 minutes ago, jenya7 said:

Есть какие то подводные камни?

Реентерабельность. Точнее, полное её отсутствие.

 

5 minutes ago, jenya7 said:

повышается читаемость функции - видишь какими переменными она оперирует

Не должна в большинстве случаев функция оперировать глобальными объектами.

Share this post


Link to post
Share on other sites
1 hour ago, aaarrr said:

Реентерабельность. Точнее, полное её отсутствие.

 

Не должна в большинстве случаев функция оперировать глобальными объектами.

Реентерабельность? Что это значит?

Ну есть случаи когда глобальные переменные неизбежны.

Share this post


Link to post
Share on other sites
12 минут назад, aaarrr сказал:

Не должна в большинстве случаев функция оперировать глобальными объектами.

Почему? Если мы берём класс то относительно класса все его функции работают как раз с глобальными объектами объявленными в классе. 
Если программа целиком имеет масштабы одного класса то почему бы описание класса и не опустить. Как раз будет набор глобальных переменных и функции для работы с ними. 

Share this post


Link to post
Share on other sites
19 minutes ago, jenya7 said:

повышается переносимость функции из проекта в проект

На основании чего? И чем это будет отличаться от нестатических переменных?

19 minutes ago, jenya7 said:

повышается читаемость функции - видишь какими переменными она оперирует

То же самое без static.

19 minutes ago, jenya7 said:

Есть какие то подводные камни?

Статические переменные создаются раз и навсегда в ОЗУ. Место там резервируется под них во время процесса линковки. Соответственно эта переменная существует там всегда, пока есть питание. Прочитайте, что такое статические переменные, и где их следует действительно использовать. Один из вариантов - использовать их в обработчиках прерываний, когда нужно сохранить предыдущие результаты.

Пример:

sometype_t xTimerHandler() {
  static auto counter = 0;
  counter++; // при каждом вызове обработчика содержимое переменной counter будет увеличиваться на 1
  
  auto not_counter = 0;
  not_counter++; // а вот эта переменная КАЖДЫЙ РАЗ БУДЕТ ОБНУЛЯТЬСЯ при входе в обработчик, затем увеличиваться на 1
}

 

5 minutes ago, jenya7 said:

Реентерабельность? Что это значит?

Вызов функции из разных задач, или даже вызов функции самой себя (рекурсия). В случае со статическими переменными это невозможно.

5 minutes ago, jenya7 said:

Ну есть случаи когда глобальные переменные неизбежны.

Есть. Но статические переменные - это не глобальные переменные. Их область видимости (статических) ограничена ближайшей парой скобок {}.

Share this post


Link to post
Share on other sites
1 hour ago, haker_fox said:

Статические переменные создаются раз и навсегда в ОЗУ. Место там резервируется под них во время процесса линковки. Соответственно эта переменная существует там всегда, пока есть питание. Прочитайте, что такое статические переменные, и где их следует действительно использовать. Один из вариантов - использовать их в обработчиках прерываний, когда нужно сохранить предыдущие результаты обработчика.

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

Share this post


Link to post
Share on other sites
1 minute ago, jenya7 said:

если я оперирую глобальной переменной

Глобальная переменная - это не статическая переменная. Глобальная переменная может быть статической. Вы же говорите о локальных статических переменных.

Вы точно понимаете различие между этими типами данных? Если да, то непонятен смысл вашего вопроса.

3 minutes ago, jenya7 said:

однопоточное приложение

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

4 minutes ago, jenya7 said:

часто бывает что я бегаю по коду ищу где эта переменная

Это решается аккуратным написанием кода и профессиональной IDE. Вы же используете конкретные типы данных в угоду читаемости. Это ошибочный путь.

 

Share this post


Link to post
Share on other sites
1 hour ago, haker_fox said:

Вы же говорите о локальных статических переменных.

ну я имею ввиду что только эта функция использует переменную.

 

1 hour ago, haker_fox said:

Это решается аккуратным написанием кода и профессиональной IDE

IAR, VxWorks достаточно профессиональные, но у них периодически отсыхает индексация.

Edited by jenya7

Share this post


Link to post
Share on other sites
39 минут назад, jenya7 сказал:

В последнее время увлекся использованием статических переменных в функции. Очень удобно - повышается переносимость функции из проекта в проект, повышается читаемость функции - видишь какими переменными она оперирует.

Нет никакой связи между читаемостью или переносимостью и статичностью или не статичностью. Это как тёплое и мягкое - абсолютно перпендикулярные вещи.

 

PS: А заменять обычные локальные переменные на статические, в тех случаях когда статичность сама по себе не нужна - это говорит только об абсолютном невладении предметом (языком и технологией программирования).

Да и вобщем - с увеличением кол-ва статических переменных (там где они не нужны) переносимость естественно ухудшается.

Share this post


Link to post
Share on other sites

 

39 minutes ago, jenya7 said:

Очень удобно - повышается переносимость функции из проекта в проект,

Вообще, из проекта в проект куда удобнее переносить модули.

Share this post


Link to post
Share on other sites
12 минут назад, haker_fox сказал:

Глобальная переменная - это не статическая переменная. Глобальная переменная может быть статической. Вы же говорите о локальных статических переменных.

Вы точно понимаете различие между этими типами данных? Если да, то непонятен смысл вашего вопроса.

Судя из вопроса - автор не понимает этого различия. И это после стольких тысяч вопросов на этом форуме. Да уж.... :russian_ru:

Share this post


Link to post
Share on other sites
1 hour ago, jcxz said:

Нет никакой связи между читаемостью или переносимостью и статичностью или не статичностью. Это как тёплое и мягкое - абсолютно перпендикулярные вещи.

к примеру

uint8_t ResponseFromTube(uint8_t tube_id)
{
       static uint32_t no_ack_timeout;
       static uint32_t resp_timeout;
       static uint32_t bit_progress_timeout;
       static uint8_t st_count = 0;
       uint8_t result;
	   uint8_t task_done = 0;
  
       no_ack_timeout = globalSysTimer + (g_sfGcpcon[noAck] * 1000);
       resp_timeout = globalSysTimer + (g_sfGcpcon[rqpRto] * 1000);
  
       switch (tube_state)
       {      
            case ST_CAN_RX :
         
              if (globalSysTimer >= bit_progress_timeout)
			  {
				bit_progress_timeout = globalSysTimer + 1000;
				write_bit_process(st_count);
				st_count++;
				if (st_count > 5)
					st_count = 0;
			  }
                
                canbus_receive_one_channel(tube_id);
         
               if (globalSysTimer < no_ack_timeout)
               {
                  //и так далее
               }
         
            break;
      }    
}

при каждом вхождении в функцию мне нужны предыдущие значения

Edited by jenya7

Share this post


Link to post
Share on other sites
6 минут назад, jenya7 сказал:

к примеру


uint8_t ResponseFromЕгиу(uint8_t tube_id)
{
       static uint32_t no_ack_timeout;
       static uint32_t resp_timeout;
       static uint32_t bit_progress_timeout;
       static uint8_t st_count = 0;
       uint8_t result;
	   uint8_t task_done = 0;
  
       no_ack_timeout = globalSysTimer + (g_sfGcpcon[noAck] * 1000);
       resp_timeout = globalSysTimer + (g_sfGcpcon[rqpRto] * 1000);
  ...
}

 

И...? Вам нужно срочно потратить лишнюю ОЗУ в программе и Вы не знаете как это сделать? Тогда да - это подойдёт. Если только оптимизатор не окажется умнее написавшего сиё и не удалит ненужные выделения памяти.

И больше не для чего.

Share this post


Link to post
Share on other sites
41 минуту назад, jenya7 сказал:

Есть какие то подводные камни?

Ну, например, в плюсах конструктор такой переменной вызывается во время первого вызова функции. Во время всех остальных вызовов на проверку "а не первый ли это вызов функции" бесполезно тратится время.

Статическими в Сях имеет смысл делать локальные переменные-константы. 

Share this post


Link to post
Share on other sites
9 minutes ago, jcxz said:

Если только оптимизатор не окажется умнее написавшего сиё и не удалит ненужные выделения памяти.

Увы, не удалит :mda:

Слово static - это как заклинание для компилятора и линкера. Ну, по крайней мере с теми  компиляторами, с которыми я работал 

 

 

имхо, если static и приписывать, то лучше к глобальным объектам (вынесенным из функции), дабы сделать их доступными только в пределах одного объектного файла. И то лишь временно. Потом все равно их нужно рассовывать по private полям классов.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now