Компилятор не настолько умный чтобы рассматривать все возможные ветви условий, тем более ваша переменная могла быть изменена где-то в коде по пути от инициализации до условия. Да и условие могло быть и посложнее. Компиляторы такие ситуации не разруливают настолько глубоко, этим занимаются отдельные статические анализаторы кода. Если хотите чтобы начальное значение Х было равно 5 то так и сделайте. Такая инициализация значением переменной X как у вас сомнительна в плане надёжности, хоть алгоритм и очевиден с первого взгляда. Но не всегда будет так.
В даном примере я с Вами согласен, но в реальном проэкте у меня задача немного сложнее. Вместо X мне нада прочесть с памяти программ значения структур меню. Переменная status - переменная флагов, которая получает своё значение от функции управления Console(), и в другом месте функции не изменяется. В момент входа в функцию func() в переменной флагов устанавливается флаг (в примере бит 1) "флаг изменения уровня" и производится чтение параметров 0-го (корневого) уровня меню. В цикле производится перемищение по пунктам меню текущего уровня (без повторной чтения параметров уровня меню). И только когда возвращается функцией Console() значение с установленным "флагом изменения уровня" производится цтение параметров нового уровня. До этого подобные алгоритмы делал на ассемблере и для того чтобы не дублировать код при начальной инициализации и переходах между уровнями, использовалась установка "флага изменения уровня" при входе в меню. Но в отличии от ассемблера, Си сам выполняет оптимизацию, и на начальных этапах освоения особенностей програмирования на Си, предупреждения подобного рода вызывают сомнения в надёжности такого кода. На ассемблере подобный метод вопросов в плане надёжности не вызывает, и уже проверен в разных устройствах. А вот с Си пытаюсь разобраться, что я делаю не так...
В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам. Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека). Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать. А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов
Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам. Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека). Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать. А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов
Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
Спасибо за разъяснение, именно в этом и был вопрос. При написании кода на ассемблере пытаешся сделать код максимально компактным и оптимальным с точки зрения расхода "тактов", но вот при попытке подобного подхода в Си иногда стал получать такие предупреждения.
Форумчане, прошу совет: надо передать в функцию указатель на значение типа char, при том что параметром функции является указатель на тип int. Реализовал с помощью буфера int, копирую туда значение, вызываю функцию, после чего востанавливаю значение с буфера. Какой подход будет более коректным не изменяя тип значения char?
Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.
unsigned int ch; unsigned int vin; unsigned int mih; volatile unsigned int eig; } vremu={10,23,45,0};
void chitaem( time *vremu){ // error: expected ')' before '*' token vremu.eig=vremu.vin+12; }
Вот нашёл в своих старых записях, решил применить да что то не выходит пишет ошибку, но раньше компилировалось, кажется. Помогите связать функцию и структуру?
Что такое time и в чём отличие от teme? Потом, vremu - указатель, поэтому доступ к элементам - либо через (*vremu).ch, либо через vremu->ch. Поэтому так:
Код:
struct time { unsigned int ch; unsigned int vin; unsigned int mih; volatile unsigned int eig; } vremu = {10,23,45,0};
Вообще, если это vremu (что за странное название, кстати?) одно, то ничто не мешает эту функцию вообще без параметров сделать. Ну а если не одно - то красивее получается так:
Код:
typedef struct { unsigned int ch; unsigned int vin; unsigned int mih; volatile unsigned int eig; } time;
time vrem0 = {10,23,45,0}; time vrem1 = {11,24,25,0}; time vrem2 = {12,42,12,0};
Плюс, если vremu (врему это время?) должно как-то со временем работать, то unsigned int для элементов структуры - это слишком, достатоно и обчного char. Всё-таки на 8бит контроллерах это существенно.
И да, интересно всё же - что скрывается под этими странными именами переменных, странно звучащими в русской транскрипции "врему", "вин", "мих", "еиг"? Просто я, например, когда пишу код, стараюсь какие-то осмысленные имена переменным давать, а тут даже близко непонятно, что это. Интригует, знаете ли.
Вопрос к ARV. хотя, и не только.)) Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании. Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно. Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции? Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
Взаимоисключающие параграфы. Быстрой реакции на прерывания при раздутом прерывании не будет. Если только при условии разрешения вложенных прерываний.... и потом разгребать непонятно как работающий индусский код. В прерывании надо быстро, как пуля, среагировать и вылететь из него. Остальное, что нужно доделать - в основном коде. Если успользуются функции в прерывании - инлайнить их в прерывание.
А их там надо быстро обрабатывать? Обычно данные надо быстро получить, а разгребать можно потом. Не часто требуется на лету обрабатывать. В общем, мало исходных данных. Точнее, их совсем нет. Что за данные, что с ними делать..
А нет ли возможности принудительно запретить формирование пролога? Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично? Инлайн, как я понимаю, не гарантирует инлайн на 100%?
И разрушить работу всей программы? Компилятор лучше знает что туда добавлять и если у него не будет повода туда что-то добавлять(код на ассемблере, например), то ничего и не создаст. Посмотрите дизассемблированный листинг, может там ничего такого и нет страшного.
Инлайнить функции в обработчик прерывания имеет смысл только для очень коротких функций, дальше 20...50 ассемблерных команд функции уже нет смысла инлайнить - выигрыш минимальный а цена слишком большая по сравнению с эффектом.
Вопрос к ARV. хотя, и не только.)) Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании. Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно. Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции? Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
OKF писал(а):
А нет ли возможности принудительно запретить формирование пролога? Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично? Инлайн, как я понимаю, не гарантирует инлайн на 100%?
если хотите, используйте "голый" обработчик прерываний
Код:
ISR(TIMER0_OVF_vect, ISR_NAKED)
в этом случае компилятор не будет генерировать ни пролог, ни эпилог функции обработчика - делайте, что хотите
если надо, чтобы функция ГАРАНТИРОВАННО инлайнилась, используйте атрибут always_inline
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 82
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения