Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Язык С, ARM - простые вопросы
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
Slash
Здравствуйте!

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

А если программа строится в виде задач в бесконечном цикле:
Код
while (1)
{
    Task1();
    Task2();
    Task3();
}

Как обмениваться сообщениями между задачами? Мне понравилась система глобальных флагов - данные готовы к отправке, данные приняты, какое-то действие завершено и т.д.
Как без них?
aaarrr
Цитата(Slash @ Jan 21 2009, 18:17) *
Стоит ли пользоваться глобальными переменными и можно ли без них обойтись?
В книгах пишут, что глобальные переменные - плохой тон, можно запутаться.

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

Цитата(Slash @ Jan 21 2009, 18:17) *
Мне понравилась система глобальных флагов - данные готовы к отправке, данные приняты, какое-то действие завершено и т.д.
Как без них?

Нормальная система.
Demeny
Цитата(Slash @ Jan 21 2009, 18:17) *
Стоит ли пользоваться глобальными переменными и можно ли без них обойтись?
В книгах пишут, что глобальные переменные - плохой тон, можно запутаться.

Правильно пишут. Пока проект небольшой (до 10 файлов на С) - это несущественно, а в больших проектах (особенно многопоточных) обилия глобальных переменных лучше избегать - замучаетесь с отладкой.
Кроме того, следование этому принципу побуждает программиста к грамотной структуризации кода, в котором каждая функция выполняет строго определённую задачу, имеет набор входных и выходных данных, которые, собственно, и передаются через параметры функции, а не выносятся в глобальные переменные.
Цитата(Slash @ Jan 21 2009, 18:17) *
А если программа строится в виде задач в бесконечном цикле:
Код
while (1)
{
    Task1();
    Task2();
    Task3();
}

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

Например, так.
Код
while (1)
{
    int Msg1, Msg2, Msg3;
            
    Task1(&Msg1, &Msg2);
    Task2(&Msg3, &Msg2);
    Task3(&Msg1);
}
aaarrr
Цитата(Demeny @ Jan 22 2009, 11:33) *
Правильно пишут. Пока проект небольшой (до 10 файлов на С) - это несущественно, а в больших проектах (особенно многопоточных) обилия глобальных переменных лучше избегать - замучаетесь с отладкой.

Поясните, пожалуйста, каким это образом глобальные переменные мешают отладке?
Demeny
Цитата(aaarrr @ Jan 22 2009, 12:09) *
Поясните, пожалуйста, каким это образом глобальные переменные мешают отладке?

При их обилии, они запутывают логику выполнения программы (и без того запутанную smile3046.gif ). Поскольку инициализируется переменная в одном месте, модифицируется в другом, а используется ещё в десятке разных мест (на то она и глобальная переменная).
Также им нужно придумывать уникальные имена, а при сходной функциональности эти имена будут примерно такие - Counter27, Sigma7, Delta18, Sum88, что тоже не добавляет читабельности коду.
aaarrr
Для отладки глобальные переменные наоборот удобнее, так как видны всегда. Иногда даже лучше временно заменить локальные переменные на глобальные, чтобы видеть результаты промежуточных вычислений.

Уникальные и осмысленные имена нужно просто научиться придумывать, имена типа Counter27, Sigma7 возникают как раз из-за недостатка этого умения.

Без глобальных переменных обойтись нельзя. Попытка использовать локальную переменную там, где нужна глобальная, запутает программу гораздо сильнее. Поэтому книжные утверждения, что де "плохой тон" следует отметать как бредовые. Нужно просто разумно использовать и те, и другие.
Demeny
Цитата(aaarrr @ Jan 22 2009, 14:29) *
Для отладки глобальные переменные наоборот удобнее, так как видны всегда. Иногда даже лучше временно заменить локальные переменные на глобальные, чтобы видеть результаты промежуточных вычислений.

Это справедливо, если проект маленький.
В большом проекте отладку каждого модуля (функции) удобно производить отдельно, особенно если они написаны разными людьми. Для этого нужно уметь быстро собрать модуль и проверить (отладить) его функционирование. А если он усеян декларациями "extern ...", то мало того, что для его запуска потребуется определять все эти переменные локально, так ещё и сделает этот модуль нелинкуемым в составе проекта, если ту или иную глобальную переменную удалят другие разработчики. Всё это влечёт за собой геморрой необходимость ведения Конвенции по глобальным переменным в рамках проекта, и т. п.
И ещё важный момент. Если Вы в своём модуле "нечаянно" измените логику работы с глобальным объектом, остальные разработчики об этом так и не узнают, только программа из-за возможной Вашей ошибки в целом может оказаться в один момент неработоспособной, и простыми средствами "поймать за руку" поломавшийся модуль не представляется возможным, повторюсь, особенно в многопоточном приложении. Зато если Вы поменяете перечень вызываемых параметров, их тип или количество ( "ну, не использую я более переменную Sum --> удаляю её из перечня параметров моей функции!" ) - это тут же выяснится ещё на этапе компиляции-линковки, и остальные разработчики смогут внести изменения в свои тексты.

Цитата(aaarrr @ Jan 22 2009, 14:29) *
Попытка использовать локальную переменную там, где нужна глобальная, запутает программу гораздо сильнее. Поэтому книжные утверждения, что де "плохой тон" следует отметать как бредовые. Нужно просто разумно использовать и те, и другие.

Там, где действительно нужна глобальная переменная, заменить её локальной невозможно в принципе - локальная будет "не видна" остальным. Никто ведь и не говорит, что от них нужно отказаться совсем. Речь идёт о том, что использовать глобальную переменную там, где запросто можно обойтись локальной - это плохой стиль программирования, "дурной тон".
--------------------------
Такая же история с оператором "goto". В принципе, в С можно без него обойтись. Но есть случаи, где его применение улучшает читабельность и логическую структуру кода, проще говоря, удобно. Однако заменять все циклы оператором "goto" - это "дурной тон".
aaarrr
Цитата(Demeny @ Jan 22 2009, 15:35) *
Всё это влечёт за собой геморрой необходимость ведения Конвенции по глобальным переменным в рамках проекта, и т. п.

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

Цитата(Demeny @ Jan 22 2009, 15:35) *
Никто ведь и не говорит, что от них нужно отказаться совсем. Речь идёт о том, что использовать глобальную переменную там, где запросто можно обойтись локальной - это плохой стиль программирования, "дурной тон".

Разумеется, но обратная ситуация - не менее, если не более дурной.
VladimirYU
Цитата(aaarrr @ Jan 22 2009, 14:29) *
Для отладки глобальные переменные наоборот удобнее, так как видны всегда. Иногда даже лучше временно заменить локальные переменные на глобальные, чтобы видеть результаты промежуточных вычислений.


Для этого достаточно одной глобальной переменной, которая удаляется после окончания отладки. Как правило, даже в сложном, но грамотно спроектированном проекте, глобальных переменных единицы.
zltigo
Цитата(VladimirYU @ Jan 22 2009, 14:52) *
Как правило, даже в сложном, но грамотно спроектированном проекте, глобальных переменных единицы.

Глупости то какие sad.gif у меня вот прямо сечас добрых 64K глобальных динамичеки создаваемых структур (не считая прочих глобальных )по которым бегают десятки подпрограмм.

Смею утверждать, что проект cпроектирован грамотно smile.gif.
aaarrr
Цитата(VladimirYU @ Jan 22 2009, 15:52) *
Для этого достаточно одной глобальной переменной, которая удаляется после окончания отладки.

И что же с этой переменной делать? Промежуточный результат - это не обязательно одинокий int.
sergeeff
Это скорее организационная проблема. Один человек ведет весь проект или коллектив. При коллективной работе глобальные переменные раскиданные по разным модулям и библиотекам - абсолютный кошмар для программистов.
zltigo
Цитата(sergeeff @ Jan 22 2009, 17:14) *
Это скорее организационная проблема.



Это ВООБЩЕ НЕ ПРОБЛЕМА и уж тем более не организационая. Либо глобальные данные принципиально нужны, либо нет.
Цитата
При коллективной работе глобальные переменные раскиданные по ...

Хоть при коллективной, хоть любой другой РАБОТЕ а бездумном бумагомарательстве, глобальные данные, структуры, поля, биты описываются ЕДИНОЖДЫ в хидерах. Дополнительно для доступа к данным c целью сокрытия ненужных подробностей можно иметь макросы/функции. И никакого кошмара.
singlskv
Цитата(Demeny @ Jan 22 2009, 15:35) *
Это справедливо, если проект маленький.
ИМХО, это совсем не так, ну посмотрите на Linux например...
Цитата
В большом проекте отладку каждого модуля (функции) удобно производить отдельно, особенно если они написаны разными людьми. Для этого нужно уметь быстро собрать модуль и проверить (отладить) его функционирование. А если он усеян декларациями "extern ...", то мало того, что для его запуска потребуется определять все эти переменные локально, так ещё и сделает этот модуль нелинкуемым в составе проекта, если ту или иную глобальную переменную удалят другие разработчики. Всё это влечёт за собой геморрой необходимость ведения Конвенции по глобальным переменным в рамках проекта, и т. п.
По моему Вы смешиваете в одном понятии совсем разные вещи,
глобальные это те переменные которые заводятся вне функций, все... (утрированно конечно)
Вы можете сделать их доступными для других модулей(например через extern), а можете и не делать,
более того Вы можете сделать их доступными для одной части других модулей и недоступными для другой(например через препроцессор, ну или еще много как).

"Конвенции по глобальным переменным в рамках проекта" не относяться ко всем глобальным переменным(если конечно это не было целью).

В качестве примера, пусть есть некий программный автомат который чего-нить там куда-нить отсылает/пишет/итд
Так вот у него есть функции или глобальные переменные видимые из вне которые запускают действие, и есть
например глобальные переменные видимые из вне которые показывают состояние выполнения, а еще есть
куча ГЛОБАЛЬНЫХ но невидимых из вне переменных которые содержат в себе все внутреннее состояние автомата.
Такой модуль вполне независим и множество таких модулей может работать в одной проге не мешая друг другу,
нужно только описать "Конвенцию..." по входным и выходным параметрам.
rezident
Я бы предложил спорщикам уточнить, для какой области приложений они обсуждают полезность/вредность глобальных переменных? Одно дело писать под Windows, где размеры стека и кучи особо не волнуют программиста. И совсем другое дело писать для МК с очень ограниченными ресурсами ОЗУ, где "наползание" стека на область статических данных нередкая и весьма трудновылавливаемая ошибка. Вот где нужно искать компромисс между глобальными/статическими и локальными (стековыми) переменными!
Demeny
Цитата(singlskv @ Jan 23 2009, 03:27) *
В качестве примера, пусть есть некий программный автомат который чего-нить там куда-нить отсылает/пишет/итд
Так вот у него есть функции или глобальные переменные видимые из вне которые запускают действие, и есть
например глобальные переменные видимые из вне которые показывают состояние выполнения, а еще есть
куча ГЛОБАЛЬНЫХ но невидимых из вне переменных которые содержат в себе все внутреннее состояние автомата.
Такой модуль вполне независим и множество таких модулей может работать в одной проге не мешая друг другу,
нужно только описать "Конвенцию..." по входным и выходным параметрам.

Вот об этом и речь ! Именно такой стиль ведения проекта мне, например, не нравится.
Предположим, Ваш модуль реализует некий программный автомат который чего-нить отсылает/пишет/итд, например, в UART. Всё внутреннее своё состояние он хранит в ГЛОБАЛЬНЫХ статических переменных.
Теперь мне нужно прикрутить в проект второй UART с той же функциональностью, третий, четвёртый ... И вообще - я, как менеджер проекта, не знаю, сколько у заказчика будет UART-ов. Как мне Ваш модуль с минимальными доработками несколько раз включить в проект ?
rezident
Цитата(Demeny @ Jan 23 2009, 12:34) *
Теперь мне нужно прикрутить в проект второй UART с той же функциональностью, третий, четвёртый ... И вообще - я, как менеджер проекта, не знаю, сколько у заказчика будет UART-ов. Как мне Ваш модуль с минимальными доработками несколько раз включить в проект ?
Что-то я не понял затруднений. Статические переменные объявленные внутри функции имеют область видимости в пределах этой функции. Статические переменные объявленные вне какой-либо функции имеют область видимости в пределах данного модуля. Разве не так?
Могу конечно ошибаться, но по-моему singlskv имел в виду как раз такой случай. Глобальная переменная (объявленная вне тела функции) типа static имеет область видимости в пределах данного модуля. Никто не мешает дублировать эти модули в требуемых количествах. Хотя конечно же, если модуль состоит из одной функции, то разумнее было бы объявить эти переменные как static, но внутри самой функции.
singlskv
Цитата(rezident @ Jan 23 2009, 18:10) *
Могу конечно ошибаться, но по-моему singlskv имел в виду как раз такой случай. Глобальная переменная (объявленная вне тела функции) типа static имеет область видимости в пределах данного модуля. Никто не мешает дублировать эти модули в требуемых количествах. Хотя конечно же, если модуль состоит из одной функции, то разумнее было бы объявить эти переменные как static, но внутри самой функции.
примерно это я и имел в виду,
только одна функция это частный случай и тогда действительно переменные нужно определять как статические внутри функции,
а вот если несколько функций в модуле работают с одной статической переменной, то без глобальных определений никак не обойтись,
но ведь можно ограничить область видимости таких переменных...

Я вот совсем теперь не понимаю за что ратует Demeny,
совсем без глобальных переменных ну никак.., и сохранение состояния автомата это один из примеров,
возможно речь о том что не нужно к ним обращаться напрямую ? то есть нужно предоставить интерфейс через вызов функций ?
ну дык это и не очень большой вопрос, и в каждом проекте он решаеться в частном порядке...
A. Fig Lee
Цитата(singlskv @ Jan 22 2009, 19:27) *
В качестве примера, пусть есть некий программный автомат который чего-нить там куда-нить отсылает/пишет/итд
Так вот у него есть функции или глобальные переменные видимые из вне которые запускают действие, и есть
например глобальные переменные видимые из вне которые показывают состояние выполнения, а еще есть
куча ГЛОБАЛЬНЫХ но невидимых из вне переменных которые содержат в себе все внутреннее состояние автомата.
Такой модуль вполне независим и множество таких модулей может работать в одной проге не мешая друг другу,
нужно только описать "Конвенцию..." по входным и выходным параметрам.


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

доступ ко всем можно организовать через проперти механизм (get/set).

польза явно осчущается когда работают человек 20 на одном проекте, чтоб не лезли шаловливыми ручками в чужой код.
Goodefine
Я, вот, по простому спрошу...
Допустим, имеем обработчик некоторого прерывания, в котором надо быстро выполнить неотложные действия и установить один или несколько флагов, дабы потом, в основном цикле их неспешно обработать. Как правильно передать эти флаги в основной цикл не используя глобальных переменных?
A. Fig Lee
Цитата(Goodefine @ Jan 23 2009, 14:09) *
Я, вот, по простому спрошу...
Допустим, имеем обработчик некоторого прерывания, в котором надо быстро выполнить неотложные действия и установить один или несколько флагов, дабы потом, в основном цикле их неспешно обработать. Как правильно передать эти флаги в основной цикл не используя глобальных переменных?


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

Иногда , на маломощных системах, использовать глобальные переменные выгодно из-за быстродействия.

Частный случай этого описал Goodefine двумя постами выше.
VladimirYU
Цитата(A. Fig Lee @ Jan 24 2009, 06:01) *
правильно будет использовать глобальные переменные.
пойнт в том, что их много быть не должно. если их 60 килобайт, как тут пишут - скорее всего чтото не так в консерватории (общий случай сферического коня в ваккууме)

Да, сложно представить консерваторию, где в оркестре все музыканты играют по одной для всех партитуре и одновременно каждый норовит ее подправить на свой вкус.
zltigo
Цитата(A. Fig Lee @ Jan 24 2009, 05:01) *
пойнт в том, что их много быть не должно.

Опять sad.gif пустые рекомендации. Их должно быть столько, сколько надо.
Цитата(VladimirYU @ Jan 24 2009, 10:23) *
Да, сложно представить консерваторию, где ..

Несколько каналов связи. За каждым свои настройки, состояния, буфера. Просто нужно поднять протокол, ну возьмем что-нибудь простое классическое 70x годов прошлого века LAPB/MLP/X.25. Вашими образами - все должно играть по одной партитуре, хотя музыканты вообще сидят в разных городах и правят друг друга по сбоящему каналу связи. Вполне обычная задача для периферийного контроллера. Начинайте расширять свои представления о жизни в которой есть не только "контролеры светодиодов".   
_Pasha
Цитата(zltigo @ Jan 24 2009, 11:47) *
Их должно быть столько, сколько надо.
Тема из разряда "что лучше : лог."0" или лог."1" . Автору - лечиться водкой до исчезновения состояния вопроса. Одну и ту же задачу можно решить более чем одним способом, критерий правильности которого лежит вне постановки решаемой задачи.
A. Fig Lee
Цитата(zltigo @ Jan 24 2009, 03:47) *
Опять sad.gif пустые рекомендации. Их должно быть столько, сколько надо.

Несколько каналов связи. За каждым свои настройки, состояния, буфера. Просто нужно поднять протокол, ну возьмем что-нибудь простое классическое 70x годов прошлого века LAPB/MLP/X.25. Вашими образами - все должно играть по одной партитуре, хотя музыканты вообще сидят в разных городах и правят друг друга по сбоящему каналу связи. Вполне обычная задача для периферийного контроллера. Начинайте расширять свои представления о жизни в которой есть не только "контролеры светодиодов".   


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

я се предстваляю TCP/IP где все глобальное - все данные сокетов и т.д.
sad.gif

ето как кернел - который глобальный для взаимосвязи, остальное все в юзерленд
zltigo
Цитата(A. Fig Lee @ Jan 24 2009, 20:14) *
но все они в глобальном спейсе - плохой дизайн.

Ага, все они в стеке это даже не "дизайн" это просто бред.

Цитата
глобально может быть виден номер канала


Упаси бог! "номер канала" ака указатель на конкретную структуру это как раз есть совершенно интимное дело функций работающими с данными каналов.

P.S.


Вы похоже совершенно путаете локальные переменные, глобальные, и области видимости глобальных. 
A. Fig Lee
Цитата(zltigo @ Jan 24 2009, 12:50) *
Ага, все они в стеке это даже не "дизайн" это просто бред.



Упаси бог! "номер канала" ака указатель на конкретную структуру это как раз есть совершенно интимное дело функций работающими с данными каналов.

P.S.


Вы похоже совершенно путаете локальные переменные, глобальные, и области видимости глобальных. 


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

Так, как я говорил - пишется подавляющее большинство програм.

Кстати, как вы к елементам структуры канала обращаетесь, если
Demeny
Цитата(singlskv @ Jan 23 2009, 18:57) *
Я вот совсем теперь не понимаю за что ратует Demeny ...

Попробую ещё раз пояснить преимущества локальных переменных перед глобальными, пусть даже и статическими, т. е. видимыми в пределах одного программного модуля.
1) Если Ваш конечный автомат, или другой программный модуль (функция) хранит своё внутреннее состояние в статических или глобальных переменных, он тут же становится непригодным для многопоточного использования, проще говоря, становится "non-reenterable", во всяком случае, Вам придётся прибегнуть к специальным ухищрениям навроде синхронизации, чтобы использование Ваших функций в многопоточном приложении не вызвало крах всего приложения. Также она не может быть безопасно вызвана в качестве обработчика прерывания.
В случае локальных переменных всё безопасно - ведь у каждого потока свой стек, следовательно, каждый поток работает со своим уникальным набором переменных.
2) Ваш модуль в составе программы может вообще оказаться невостребованным (ну нет у клиента 8 UART-ов, заложенных по максимуму ...), однако память под буфера и прочие настройки Вы уже зарезервировали статически. Или же Ваш модуль нужен только на этапе инициализации - один раз при старте системы, а память занята уже "навсегда" ...
3) Доступ к локальным переменным осуществляется, как правило, быстрее, чем к глобальным (статическим), потому что любой оптимизирующий компилятор старается раскидать по возможности локальные переменные по регистрам процессора.
4) С точки зрения проектирования удобно представлять себе отдельную функцию, как законченный функциональный блок ("черный ящик") с входными и выходными параметрами. Это позволяет отлаживать функцию отдельно от остальных. Использование глобальных переменных размывает это понятие, поскольку, как ни крути, поведение функции зависит от поведения остальной части программы. Вот и будем ломать голову при отладке, какого же рожна глобальная переменная имеет "не то" значение, какое должно быть, и какая собака его испортила. Придётся бросить отладку текущей функции и заняться поиском "собаки". unsure.gif
zltigo
Цитата(Demeny @ Jan 26 2009, 12:58) *
1) Если Ваш конечный автомат, или другой программный модуль (функция) хранит своё внутреннее состояние в статических или глобальных переменных, он тут же становится непригодным....


Либо с точностью до наоборот - ПРИГОДНЫМ. Конечный автомат получает указатель на структуру с котрой работать в данный момент и работает. Кроме того, опять, если нужны сколь нибудь реально-сложные автоматы в многопоточном приложении, то по любому он нужен и эти проблемы придется решать и отнюдь "просто используем локальные переменные".

Цитата
Вы уже зарезервировали статически.


Статически-то зачем? Спросили сколько надо у менеджера памяти. А вот стек, который потребуется Вам для Вашего непрогнозируемого количества "UART-ов" Вы как раз скорее всего статически-то и выделите. 

Цитата
3) Доступ к локальным переменным осуществляется, как правило, быстрее, чем к глобальным (статическим)


Из каждого "правила" есть исключения. Причем "как правило" они очень мешают жить. 

Цитата
.. поведение функции зависит от поведения остальной части программы.



Либо поведение этой функции ДОЛЖНО ЗАВИСЕТЬ от "остальной части" и тут Вас никакие ухищрения не заставят обойти эту зависимость. Либо НЕ зависят - в этом случае глубоко фиолетов глобальные или нет какие-то переменные, ибо в этом случае они по любому приватно находятся в пользовании одной функции.

 
Dog Pawlowa
Цитата(Demeny @ Jan 26 2009, 12:58) *
Попробую ещё раз пояснить ...

Этап системного проектирования, постановки задачи и разбиения задачи на подзадачи вообще-то присутствует?
Вот и выбирается на этом этапе все, включая способы взаимодействия, ресурсы, особенности.
В общем случае "глобальность против локальности" не имеет решения. Та же "реентерабельность". Почему printf не реентерабельный, не задумывались? Почему разработчики компиляторов не хотят осчастливить страждущих?
_Pasha
Цитата(Dog Pawlowa @ Jan 26 2009, 13:45) *
В общем случае "глобальность против локальности" не имеет решения. Та же "реентерабельность".

Есть костыли - работать с указателем на структуру, содержащую "локальные" параметры функции, являющейся де-юре нереентерабельной. Если шаловливые ручки добираются до таких решений, то что это? (Что такое хорошо и что такое плохо?)
A. Fig Lee
Цитата(zltigo @ Jan 26 2009, 05:32) *
Статически-то зачем? Спросили сколько надо у менеджера памяти. А вот стек, который потребуется Вам для Вашего непрогнозируемого количества "UART-ов" Вы как раз скорее всего статически-то и выделите. 

 


Товарищи капиталисты, по-моему вы путаете теплое с мягким.

Глобальное - то, что видно отовсюду и всегда живет (возможно спорно),
Локальное - определено и живет в пределах обьекта к которому принадлежит.
Пример - переменные обьявленные внутри функции - локальные для етой функции (
совсем не обязательно они должны быть на стеке),
переменные обьявленные внутри класс/структуры - локальны для етих
классов/структур и глобально (без структуры/класса) - невидимы.
Могут размещатся в хипе, от етого глобальными не становятся.
_Pasha
Цитата(A. Fig Lee @ Jan 26 2009, 18:20) *
Товарищи капиталисты, по-моему вы путаете теплое с мягким.
Глобальное - то, что видно отовсюду и всегда живет (возможно спорно),

Статическое - это то, что видно только там, где надо, и всегда живет. Не путайте мертвое  с пьяным smile.gif
Dog Pawlowa
Цитата(_Pasha @ Jan 26 2009, 14:13) *
Есть костыли - работать с указателем на структуру, содержащую "локальные" параметры функции, являющейся де-юре нереентерабельной.

Насколько я понимаю, такое решение увеличивает размер требуемой программной памяти - адреса параметров нужно вычислять по указателю на структуру.
zltigo
Цитата(A. Fig Lee @ Jan 26 2009, 17:20) *
Товарищи капиталисты, по-моему вы путаете теплое с мягким.



Это у Вас каша sad.gif из глобальности и области видимости, на что я уже сразу указывал.
_Pasha
Цитата(Dog Pawlowa @ Jan 26 2009, 18:10) *
 адреса параметров нужно вычислять по указателю на структуру.

Вообще-то нет, если используется доступ к локальным переменным через [регистр базы + смещение]. Один раз добрались до адреса- и все.
zltigo
Цитата(_Pasha @ Jan 26 2009, 18:23) *
Один раз добрались до адреса- и все.


Угу! Удобно. Экономия при наличии у контроллера нужных режимов адресации в чистом виде.
A. Fig Lee
Цитата(_Pasha @ Jan 26 2009, 09:49) *
Статическое - это то, что видно только там, где надо, и всегда живет. Не путайте мертвое  с пьяным smile.gif



смотря о каких языках говорил - C или C++?

2. живет не всегда. например, обьявленная внутри функции - с момента обращения к функции.


Цитата(zltigo @ Jan 26 2009, 10:22) *
Это у Вас каша sad.gif из глобальности и области видимости, на что я уже сразу указывал.


видимость переменной может быть и глобальной, но она являтся локальной -
обьявить паблик мембер - член класса
_Pasha
Цитата(A. Fig Lee @ Jan 26 2009, 21:55) *
2. живет не всегда. например, обьявленная внутри функции - с момента обращения к функции.

Присмотритесь повнимательнее:  статические переменные живут изначально благодаря статической компиляции. И инициализация их (значением) производится в теле стартапа Поскольку это самое недорогое и здравое решение проблемы - позволить компилятору решить, где расположить переменную, оно применяется чаще всего.
singlskv
Цитата(A. Fig Lee @ Jan 26 2009, 20:55) *
2. живет не всегда. например, обьявленная внутри функции - с момента обращения к функции.
Живет она как раз всегда, а вот увидеть ее мы можем другой функцией
только после обращения к фунцкии в которой она определена(а можем и не увидеть если не захотим...).

Вот с вашей точки зрения в таком коде:
Код
void someFunc()
{
  static unsigned char ch;
  ................
}

переменная ch глобальная или локальная ?


Разница между глобальными и локальными ИМХО, заключается в том что к глобальной(если захочу), могу обратиться
из любой другой функции, а вот к локальной только из функции в которой она создана.
sonycman
Цитата(_Pasha @ Jan 26 2009, 22:33) *
статические переменные живут изначально благодаря статической компиляции. И инициализация их (значением) производится в теле стартапа

А если статическая переменная локальная? Разве её инициализация будет производиться в стартапе?
singlskv
Цитата(sonycman @ Jan 26 2009, 23:17) *
А если статическая переменная локальная? Разве её инициализация будет производиться в стартапе?
Переменная из моего предыдущего поста статическая и объявлена в теле функции,
ее инициализация будет проведена в стартапе.



Более того(если захотеть), менять ее можно будет и из другой функции.
rezident
Цитата(singlskv @ Jan 27 2009, 01:27) *
Более того(если захотеть), менять ее можно будет и из другой функции.
Я извиняюсь, что вмешиваюсь. Работать с этой переменной в другой функции можно будет только по указателю, который данная функция должна сообщить другой, но не по символическому имени переменной.
Я тут некоторое время назад пояснял одному (точнее одной smile.gif ) пользователю о типах переменных. Может интересно будет.
sonycman
Цитата(singlskv @ Jan 27 2009, 00:27) *
Переменная из моего предыдущего поста статическая и объявлена в теле функции,
ее инициализация будет проведена в стартапе.

А мне тут недавно говорили, что статические локальные переменные инициализируются при первом заходе в содержащую их функцию.
И совершенно не в стартапе.
singlskv
Цитата(rezident @ Jan 26 2009, 23:40) *
Работать с этой переменной в другой функции можно будет только по указателю,
который данная функция должна сообщить другой, но не по символическому имени переменной.

Я это и имел в виду.("менять ее можно будет...")

Цитата(sonycman @ Jan 27 2009, 00:07) *
А мне тут недавно говорили, что статические локальные переменные инициализируются при первом заходе в содержащую их функцию.
И совершенно не в стартапе.

Вас обманули... smile.gif

Ну то есть, конечно, можно представить себе компилятор который будет так поступать,
только это очень не эффективно.

Ну и главное что память под такую переменную уже будет отведена компилятором, те к моменту первого
запуска ее адрес будет постоянным.
sonycman
Цитата(singlskv @ Jan 27 2009, 01:29) *
Вас обманули... smile.gif

Ну то есть, конечно, можно представить себе компилятор который будет так поступать,
только это очень не эффективно.

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

Да, проверил - простые встроенные типы к моменту первого входа в функцию уже инициализированы.

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

То есть статические локальные объекты всё таки несут в себе определённый оверхед...
A. Fig Lee
Цитата(singlskv @ Jan 26 2009, 14:45) *
Вот с вашей точки зрения в таком коде:
Код
void someFunc()
{
  static unsigned char ch;
  ................
}

переменная ch глобальная или локальная ?


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


ok.

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

6.2.4 Storage durations of objects
1 An object has a storage duration that determines its lifetime. There are three storage
durations: static, automatic, and allocated. Allocated storage is described in 7.20.3.
2 The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it.
An object exists, has a constant address,25) and retains
its last-stored value throughout its lifetime.26) If an object is referred to outside of its
lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.
3 An object whose identifier is declared with external or internal linkage, or with the
storage-class specifier static has static storage duration. Its lifetime is the entire
execution of the program and its stored value is initialized only once, prior to program
startup.
4 An object whose identifier is declared with no linkage and without the storage-class
specifier static has automatic storage duration.
5 For such an object that does not have a variable length array type, its lifetime extends
from entry into the block with which it is associated until execution of that block ends in
any way.
(Entering an enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively, a new instance of the
object is created each time. The initial value of the object is indeterminate. If an
initialization is specified for the object, it is performed each time the declaration is
reached in the execution of the block; otherwise, the value becomes indeterminate each
time the declaration is reached.
6 For such an object that does have a variable length array type, its lifetime extends from
the declaration of the object until execution of the program leaves the scope of the
declaration.27) If the scope is entered recursively, a new instance of the object is created
each time. The initial value of the object is indeterminate.
zltigo
Цитата(A. Fig Lee @ Jan 27 2009, 01:07) *
Онако - время жизни статической переменной внутри функции
определено со времени входа в функцию


О господи! Конечно нет. Вы бы хоть РЕАЛЬНО прочитали, то что процитировали.
singlskv
Цитата(A. Fig Lee @ Jan 27 2009, 01:07) *
Немного неправильно обозвал глобальные, да.
ага, неправильно, и выделить нужно было другой текст:
3 An object whose identifier is declared with external or internal linkage, or with the
storage-class specifier static has static storage duration. Its lifetime is the entire
execution of the program and its stored value is initialized only once, prior to program
startup.

Обращу Ваше внимание что в этом пункте вобще ничего не сказанно про место где декларируется static identifier ...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.