roboforum.ru

Технический форум по робототехнике.

 

Объявление переменной в середине кода функции.

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Объявление переменной в середине кода функции.

Сообщение viper » 11 дек 2015, 13:28

У меня откуда-то отложилась информация о том, что где-бы не была объявлена переменная в коде на машином языке она будет инициализирована при входе в функцию. Как с этим дела на ATMega обстоят? Я в прерывании, какой код будет быстрее выходить из прерывания, в случае, когда в if ложно:
1.
Код: Выделить всёРазвернуть
ISR(TIMER1_CAPT_vect) {
  unsigned int timer1CounterValue;
  timer1CounterValue = ICR1;
  if (timer1CounterValue < 0x7FFF) {
    unsigned long a = действия с глобальной переменной;
    ...
  };

3.
Код: Выделить всёРазвернуть
ISR(TIMER1_CAPT_vect) {
  unsigned int timer1CounterValue;
  timer1CounterValue = ICR1;
  unsigned long a;
  if (timer1CounterValue < 0x7FFF) {
    a = действия с глобальной переменной;
    ...
  };
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Madf » 11 дек 2015, 13:42

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

зы: все эти языковые замуты МК пофиг, все проблемы от компилятора (если они есть). Т.ч. тут "ATMega" и XMega, ARMы...не важно.
Madf
 
Сообщения: 2139
Зарегистрирован: 03 янв 2012, 12:55
Откуда: Москва
прог. языки: VB6, BASCOM, ASM...

Re: Объявление переменной в середине кода функции.

Сообщение viper » 11 дек 2015, 14:30

Я этого не умею делать, asm пока не знаю. Если кому то знающему не сложно, то просьба проверить.
Спасибо.
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Angel71 » 11 дек 2015, 14:59

из-за пары тактов целую тему подняли? дык барин если не знаете асм, так и нечего такими вопросами голову себе забивать. варианта два - начинайте изучать асм, дизасемблирование, архитектуру конкретных мк, отличия компиляторов и влияние настроек. или прекращайте задаваться бессмысленными вопросами. "Если кому то знающему не сложно, то просьба проверить" ещё раз намекаю, что разные компиляторы и/или с разными настройками могут по разному компилировать. "..." в данном огрызке кода означает, что даже нельзя предсказать, компилятор вообще выкинет эту "a" и присваивание ей или нет. :pardon: оптимизация однако. когда нужно каждый такт беречь, так код не на си пишется, а на асме. так что учите и асм вставочками делайте. и это, си продолжайте изучать - называть локальную переменную глобальной о многом говорит...
Аватара пользователя
Angel71
 
Сообщения: 9231
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Объявление переменной в середине кода функции.

Сообщение viper » 11 дек 2015, 15:43

Я не берегу каждый такт, но и раскидываться ими, особенно где код выполняется десяток раз за миллисекунду, не хочется. Но вообще при программировании придерживаюсь некоторых правил, по которым компилятор МОЖЕТ оптимизировать. Просто использую эти правила для увеличения быстродействия, а если компилятор этот момент не оптимизирует, исправить это не смогу, но каждый раз проверять стоит ли использовать это правило с компилятором для оптимизации или нет, не буду, просто буду этого правила придерживаться. К примеру, знаю, что с некоторыми компиляторами при условии if с ИЛИ, если первое выражение true, второе уже не проверяется, поэтому на первое место ставлю то выражение, которое по моим представлениям чаще другого истинно. При этом я не знаю как ведёт себя avr компилятор и использует ли такую оптимизацию. Вообще до AVR я программировал только на Object Pascal, Free Pascal. А тут в Си заинтересовала возможность объявления переменных перед первым использованием. Так код намного лучше понимаем и комментировать проще.
Из того, что удалось выяснить. Если команды asm
Код: Выделить всёРазвернуть
cpc     r25, r1
brcc    .+24

это и есть сравнение и прыжок при "false", то разницы никакой, сравнение происходит на одной и той же по счёту инструкции. Но вот размер скомпилированной программы отличается. Скомпилированная программа с объявлением переменной в начале функции, а не перед первым использованием, почему-то на 20 байтов меньше. Как в gdb дизассемблировать всю программу, а не только функцию, я пока не нашёл.
В итоге, моё исследование показало, что объявление переменной перед её использованием в блоке if на скорость до if не влияет, а вот размер программы увеличивает, почему-то. А размер программы для контролера критичен. Так что лучше объявлять переменные в начале. ИМХО. Но исследование может быть ошибочно в силу не знания asm для котроллера avr.
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Madf » 11 дек 2015, 16:06

Если вы пишите на си под атмегу, то наверняка это Авр Студия, там есть симулятор/дебайгер: https://www.youtube.com/watch?v=aAw-7Lq-3tI
Можете не зная ASM-а, просто посмотреть по тактам/времени сколько выполняется функция в разных её представлениях...
Madf
 
Сообщения: 2139
Зарегистрирован: 03 янв 2012, 12:55
Откуда: Москва
прог. языки: VB6, BASCOM, ASM...

Re: Объявление переменной в середине кода функции.

Сообщение viper » 12 дек 2015, 00:24

Спасибо.
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Dmitry__ » 12 дек 2015, 04:04

viper писал(а): Я в прерывании, какой код будет быстрее выходить из прерывания, в случае, когда в if ложно:

Код в 2-х примерах логически одинаковый. И что значит "a = действия с глобальной переменной;"? Если бы "глобальная переменная = a;" еще понятно, если "глобальная переменная = действия с локальной переменной;" опять непонятно, почему вообще справа от равно есть действо? :shock: В фразе "действия с глобальной переменной" находится весь смысл вопроса, а тема сисек не раскрыта. Это неправильно, нехорошо, нелогично. Тем более для прерываний. :)
Си в каких-то версиях начинает разрешать обьявление переменных в середине кода, ибо код с обьявлением в начале функции несильно уходит от асмовского программописания. Если откомпилить: for(int a = 0;....) в нормальных компиляторах, то будет/не будет ошибка в зависимости от флага "-std=gnu99". Как это делается в иде для лохов (платных закрытых) надо уточнять у разработчиков, т.е. звонок другу в службу поддержки, ну если не крякнутый/ворованный компилятор :)
Аватара пользователя
Dmitry__
 
Сообщения: 6000
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Объявление переменной в середине кода функции.

Сообщение Angel71 » 12 дек 2015, 05:26

объявление лонга до условия и после это как раз возня ради пары тактов. "if с ИЛИ ..." аха, размечтались. с или оно может проверить всё, а вот с или или брякает на первом тру. "но каждый раз проверять стоит ли использовать это правило с компилятором для оптимизации или нет, не буду, просто буду этого правила придерживаться" ну и ... (сам придумай, ибо со второго раза не доходит про компиляторы и настройки, а это следствие действия тормозной жидкости). в отличии от мира фантазий, в реальном мире с такой логикой вас ждут шишки на лбу и множество не очевидных вам вещей, возможно с неприятными сюрпризами. и это только компилятор, а ещё у разных камушков есть море приятных различий в архитектуре, что по глупости недоучек-оптимизаторофф легко может приводит к противоположному от желаемого эффекту. для тугоплавких повторяю элементарные азы - когда для таких хилых и примитивных мк нужно оптимизировать, то это делается на асме и только на асме - в следующем билде компилятора или студии что-то поменяется и всё, ваши все недооптимизации могут пойти в одно место, а вы об этом скорей всего даже и не узнаете. банально скопипастили код из студии в другую, а там или компилятор другой или настройки, весело... и ещё момент - оптимизируют только когда это необходимо, оптимизация ради оптимизации это не оправдано затратно, неэффективно и т.д., т.е. тупо, особенно с нулевыми знаниями и опытом. а самое смешное, когда долго и нудно некоторые тужатся с оптимизацией, а потом где в коде возьмут, да и вызовут допустим тяжеловесную библиотечную функцию, которая слопает на порядок больше тактов и/или памяти. а кроме функций ещё много чего интересного есть - типы данных, операции над переменными (банально да хоть деление или умножение, когда камушек это не умеет) и т.д. но упёршись рогами и вникая во всякую фигню вы о многих вещах или не скоро узнаете или не узнаете вообще и никогда. пока только очень заметно, что даже элементарные азы языка ещё не осилили, а уже лезите в ненужные дебри. печальное зрелище с предсказуемым результатом.
Dmitry__, с каких-то версий некоторые компиляторы вообще-то стали очень навороченными и интеллектуальными. хотя ещё не настолько интеллектуальные - с таким кодом оте дополнительные 20 байт это наверно первые робкие и неудачные попытки сделать локальную переменную глобальной.
Аватара пользователя
Angel71
 
Сообщения: 9231
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Объявление переменной в середине кода функции.

Сообщение viper » 20 дек 2015, 01:29

Angel71
Интересная у Вас манера общения, сразу с каких-то оскорблений.
Я честно говоря, так и не понял, почему вы упорно утверждаете, что я не знаю что такое глобальная переменная.
Код: Выделить всёРазвернуть
unsigned long a = действия с глобальной переменной;

Это значит, что есть объявленная глобальная переменная, пусть её название будет global, а в выделенном участке кода пусть будет присвоение локальной переменной квадрата глобальной. Итого:
Код: Выделить всёРазвернуть
unsigned long a = global*global;

Хотя нет, я догадываюсь, почему вы не поняли пример, видимо из-за малой практики, вы подумали, что я хотел привести пример вида:
Код: Выделить всёРазвернуть
unsigned long a = a*a;
, и называл переменную глобальной, так как, с ваших слов, не осилил элементарные азы языка. Но будь у вас достаточно практики, вы бы поняли, что такие действия бесполезны и не возможно получить ожидаемый результат, он будет не предсказуемый, так как переменная а не инициализирована, и что бы не было справа с участием этой переменной, результат будет иметь случайное значение. То есть такая строка вообще никакого смысла не имеет, сразу уж можно было написать
Код: Выделить всёРазвернуть
unsigned long a = 100500;
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Angel71 » 20 дек 2015, 05:14

т.е. "unsigned long a = действия с глобальной переменной;" не может означать, допустим такое "static uint32_t a += diff;"?
Код: Выделить всёРазвернуть
volatile uint8_t counter;
volatile uint16_t start, diff;

ISR(TIMER1_CAPT_vect)
{
   if (TCCR1B & 0x40) { TCCR1B &= ~0x40; start = ICR1; }
   else {
      TCCR1B |= 0x40;
      if (!(counter & 0x80)) {
         diff = ICR1;
         if (start > diff)
            diff += TOP;
         diff -= start;
         if (diff > MIN && diff < MAX)
         {
            if ((counter&(~0x80)) < 30) counter += 3;
         }
         else counter &= 0x80;
      }
   }
   static float a = a * 0.5 + (float)(counter) * 0.5;
}

значение не инициализированных переменных всегда не известны? :crazy: а, точно, разрабы реализовали забивание памяти рандомом при старте мк. есть и другие варианты, при старте будут старые или "повреждённые" данные. хотя... :ROFL: такому опытному человегу как вы, напоминать про такие мелочи каг бэ рановато - всё связанное с си и работой горстки мк с различными архитектурами если на жалкий десяток % и изучил, то уже хорошим результатом считаю.
Последний раз редактировалось Angel71 20 дек 2015, 05:49, всего редактировалось 1 раз.
Аватара пользователя
Angel71
 
Сообщения: 9231
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Объявление переменной в середине кода функции.

Сообщение Dmitry__ » 20 дек 2015, 05:49

Angel71 писал(а):т.е. "unsigned long a = действия с глобальной переменной;" не может означать, допустим такое "static uint32_t a += diff;"?

Тема сисек раскрыта :)

viper, а если я не оскорблял, пачиму нет ответов на мои вопросы? :cry:
Аватара пользователя
Dmitry__
 
Сообщения: 6000
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Объявление переменной в середине кода функции.

Сообщение Angel71 » 20 дек 2015, 06:21

ну да, раскрыта. а вдруг там после равно "Singleton::getInstance().time->getTime();" :crazy: поди разбери, что у него там за действия с глобальными переменными могут быть.
Аватара пользователя
Angel71
 
Сообщения: 9231
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

Re: Объявление переменной в середине кода функции.

Сообщение viper » 20 дек 2015, 20:15

т.е. "unsigned long a = действия с глобальной переменной;" не может означать, допустим такое "static uint32_t a += diff;"?

Я разве static указывал перед объявлением переменной? Нет не может, фантазии могут быть справа от равно.
viper
 
Сообщения: 6
Зарегистрирован: 11 дек 2015, 13:09

Re: Объявление переменной в середине кода функции.

Сообщение Angel71 » 21 дек 2015, 03:06

а, так вон оно чё, михалыч. раз хочешь, так и дальше возись с потугами оптимизации без оптимизации и почаще продолжайте игнорировать вещи, влияющие на генерируемый машинный код.
Аватара пользователя
Angel71
 
Сообщения: 9231
Зарегистрирован: 18 апр 2009, 22:18
Предупреждения: -1

След.

Вернуться в Микроконтроллеры

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 6

cron
Mail.ru counter