|
Немного стандарта написания программ на С, применительно к контроллерам |
|
|
|
Oct 26 2009, 08:20
|

Гуру
     
Группа: Свой
Сообщений: 2 113
Регистрация: 1-11-05
Пользователь №: 10 359

|
Всем привет. Разрабатываю программу для PIC24F. Необходимо более-менее придерживаться стандарта. У меня вопрос следующий... Обычно все переменные я объединяю в структуры, группирую по назначению Код typedef struct { alt_buttons* buttons; //ссылка на массив кнопок unsigned char max_key_num; //число кнопок в клавиатуре ....... unsigned char alpha; //прозрачность клавиатуры } alt_keyboard; Это удобно, т.к. список аргументов функций будет представлять собой не кучу всяких переменных, а лишь одну структуру (или несколько). Правильно, вроде как, считается создавать локальные переменные и передавать их затем в качестве аргумента. Например, в main: Цитата void main (void) { alt_keyboard keyboard;
system_init (&keyboard); Но вот необходимо обрабатывать прерывания. Как же быть там? Получается, нужно работать с глобальными переменными. Это плохо? Кто как поступает? Можно основные переменные (например, клавиатура, дисплей и т.п.) сделать глобальными и работать с ними из любой функции. Не?
--------------------
Быть. torizin-liteha@yandex.ru
|
|
|
|
|
Oct 26 2009, 08:35
|

Знающий
   
Группа: Свой
Сообщений: 943
Регистрация: 6-07-04
Из: Санкт-Петербург
Пользователь №: 274

|
Цитата(torik @ Oct 26 2009, 12:20)  Правильно, вроде как, считается создавать локальные переменные и передавать их затем в качестве аргумента. Например, в main: кем считается? первый раз такое слышу. Наоборот, если оптимизатор не отработает, то стеку будет расходоваться больше - к примеру, слово для локальной переменной и слово для передачи параметра (если через регистры все параметры передать не получится). Цитата(torik @ Oct 26 2009, 12:20)  Получается, нужно работать с глобальными переменными.Это плохо? Кто как поступает? в общем случае плохо, но иногда без этого никак, смело пользуйся
|
|
|
|
|
Oct 26 2009, 08:47
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Alex B._ @ Oct 26 2009, 12:35)  в общем случае плохо, но иногда без этого никак, смело пользуйся А чем плохо? Переменная висит статически, в заранее известном адресе, существует всё время работы. И учитывать память проще, чем когда локальные переменные вываливаются на стек
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 26 2009, 10:22
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(torik @ Oct 26 2009, 11:20)  Я следую такому правилу - делать переменную глобальную только в том случае, когда без этого - никак (например, по другому никак не передать данные в/из обработчик прерываний и тд). Где-то вычитал правило и согласен с ним. Звучит как-то так: "Предпочитайте локальные переменные - глобальным, глобальные статические - просто глобальным" Цитата(MrYuran @ Oct 26 2009, 12:47)  А чем плохо? Переменная висит статически, в заранее известном адресе, существует всё время работы. 1. именно этим и плохо. Разово нужная переменная постоянно занимает память. 2. программы с глобальными переменными очень плохо читаются (ну это мое субъективное мнение) 3. глобальная - доступна всем желающим (во всей программе, либо в единице трансляции, если это - статик). Можно посадить трудноуловимые баги  . 4, Трудность переноса кода - если функция использует только локальные переменные, ее в общем случае можно просто "взять и выдернуть". Использующая глобальные переменные функция, потянет за собой хвост этих переменных...
|
|
|
|
|
Oct 26 2009, 10:59
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(Dima_G @ Oct 26 2009, 14:22)  1. Разово нужная переменная постоянно занимает память. Если разово, то согласен - локальные. Но бывают флаги/состояния, которые нужно хранить от вызова к вызову. Не забываем также, что речь идёт о программировании контроллеров, а не ПиСи Цитата 2. программы с глобальными переменными очень плохо читаются (ну это мое субъективное мнение) 3. глобальная - доступна всем желающим (во всей программе, либо в единице трансляции, если это - статик). Можно посадить трудноуловимые баги  . 4, Трудность переноса кода - если функция использует только локальные переменные, ее в общем случае можно просто "взять и выдернуть". Использующая глобальные переменные функция, потянет за собой хвост этих переменных... И что, предлагаете в мэйне организовать глобальную свалку переменных со всего проекта, а в каждую функцию передавать десяток параметров? Может, это и правильно с т.з. высоких материй (опять же применительно к PC), но в практической работе очень неудобно. Я в процессе эволюции пришёл к созданию максимально независимых модулей со своими глобальными и статическими переменными. Те переменные, которые надо видеть "снаружи" модуля, выношу extern-ом в h-файл модуля. А main в таком случае состоит из подключения соответствующих модулей через h-файлы, инициализации и быстрого суперцикла. "Взять и выдернуть" в таком случае можно не отдельную функцию, а модуль. Да и не надо его дёргать, просто подключить и использовать.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 26 2009, 11:20
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(MrYuran @ Oct 26 2009, 14:59)  Не забываем также, что речь идёт о программировании контроллеров, а не ПиСи А в чем разница?  Цитата(MrYuran @ Oct 26 2009, 14:59)  И что, предлагаете в мэйне организовать глобальную свалку переменных со всего проекта, а в каждую функцию передавать десяток параметров? Может, это и правильно с т.з. высоких материй (опять же применительно к PC), но в практической работе очень неудобно. 1. Причем тут глобальная свалка? Не совсем пойму, что вы имеете в виду. Можете привести короткий пример? 2. Если в функцию передается больше 3х параметров (за редким исключением) - это повод задуматься о том, правильно ли разбили задачу на функции. Или возможно стоит объединить какие-то параметры в структуры. 3. Опять же - причем тут ПС? Или вы считаете, что хороший стиль на ПС и на МК отличается?
|
|
|
|
|
Oct 26 2009, 11:37
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(xemul @ Oct 26 2009, 15:05)  Ну и компилятор может не переварить volatile у локальной переменной. В первый раз слышу.. На каком компиляторе у Вас вылезла такая проблема? Часто использовал локальные volatile переменные на многих платформах - gcc powerpc, gcc arm, gcc blackfin, VisualDSP, CodeComposer - никогда не имел с этим проблеммы  Цитата(MrYuran @ Oct 26 2009, 15:22)   Ну хотя бы в том, что иногда приходится считать (кило)байты и микросекунды. В особо запущенных случаях счёт идёт на такты... Ну я понимаю  Более того, иногда и для PC (кстати, а что в вашем понимании PC? Blackfin с uClinux в него входит? А PowerPC c Linux?  ) приходится сильно оптимизировать код. Хороший программист должен писать эффективный код, хоть на дохленьком PIC, хоть на 6 ядерном TMS64+
|
|
|
|
|
Oct 26 2009, 11:48
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Dima_G @ Oct 26 2009, 14:37)  Часто использовал локальные volatile переменные на многих платформах - gcc powerpc, gcc arm, gcc blackfin, VisualDSP, CodeComposer - никогда не имел с этим проблеммы  Часто? Часто это скорее всего плохо, ибо мне известен только один случай, когда volatile применительно к локальной переменной имеет смысл, да и тот по сути есть вредительство. Не поделитесь примерами использования? Банальное любопытство мучает.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 26 2009, 11:55
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(zltigo @ Oct 26 2009, 15:48)  Часто? Часто это скорее всего плохо, ибо мне известен только один случай, когда volatile применительно к локальной переменной имеет смысл, да и тот по сути есть вредительство. Не поделитесь примерами использования? Банальное любопытство мучает. Инициализация периферии. Если этот регистр более нигде не нужен, использую его только локальной переменной Код class ClHardwareManager { static const DWORD INIT_REG_ADDR = 0x...; INT8 Init() { volatile DWORD* pdwInitReg_ = reinterpret_cast<volatile DWORD*>(INIT_REG_ADDR); *pdwInitReg_ = ... }
};
|
|
|
|
|
Oct 26 2009, 13:03
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(ReAl @ Oct 26 2009, 15:57)  Да ну... Тут у Вас локальной переменной есть pdwInitReg_, но она ни на грамм не volatile. Указывает на volatile, но на НЕ локальную.  Ну да Перепутал маленько
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|