В даном примере я с Вами согласен, но в реальном проэкте у меня задача немного сложнее. Вместо X мне нада прочесть с памяти программ значения структур меню. Переменная status - переменная флагов, которая получает своё значение от функции управления Console(), и в другом месте функции не изменяется. В момент входа в функцию func() в переменной флагов устанавливается флаг (в примере бит 1) "флаг изменения уровня" и производится чтение параметров 0-го (корневого) уровня меню. В цикле производится перемищение по пунктам меню текущего уровня (без повторной чтения параметров уровня меню). И только когда возвращается функцией Console() значение с установленным "флагом изменения уровня" производится цтение параметров нового уровня. До этого подобные алгоритмы делал на ассемблере и для того чтобы не дублировать код при начальной инициализации и переходах между уровнями, использовалась установка "флага изменения уровня" при входе в меню. Но в отличии от ассемблера, Си сам выполняет оптимизацию, и на начальных этапах освоения особенностей програмирования на Си, предупреждения подобного рода вызывают сомнения в надёжности такого кода. На ассемблере подобный метод вопросов в плане надёжности не вызывает, и уже проверен в разных устройствах. А вот с Си пытаюсь разобраться, что я делаю не так...Alexeyslav писал(а):Компилятор не настолько умный чтобы рассматривать все возможные ветви условий, тем более ваша переменная могла быть изменена где-то в коде по пути от инициализации до условия. Да и условие могло быть и посложнее.
Компиляторы такие ситуации не разруливают настолько глубоко, этим занимаются отдельные статические анализаторы кода.
Если хотите чтобы начальное значение Х было равно 5 то так и сделайте. Такая инициализация значением переменной X как у вас сомнительна в плане надёжности, хоть алгоритм и очевиден с первого взгляда. Но не всегда будет так.
WinAvr в вопросах и ответах
- Сообщения: 22
- Зарегистрирован: Сб дек 26, 2015 22:28:05
- Реклама
В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам.
Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека).
Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать.
А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов
Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека).
Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать.
А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов
Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 22
- Зарегистрирован: Сб дек 26, 2015 22:28:05
Спасибо за разъяснение, именно в этом и был вопрос. При написании кода на ассемблере пытаешся сделать код максимально компактным и оптимальным с точки зрения расхода "тактов", но вот при попытке подобного подхода в Си иногда стал получать такие предупреждения.ARV писал(а):В отличие от сообщений об ошибках, сообщения-предупреждения служат для привлечения внимания программиста к "подозрительным" местам.
Если вы не имеете аналогичных сообщений в ассемблере, то не потому, что ваш алгоритм безупречен, а потому, что ассемблер не имеет такой функции - обращать внимание на подозрительные места (да и определить такое место в ассемблере - задача та еще и для человека).
Предупреждения вообще можно отключить - будет вам полный аналог поведения ассемблера, и вы сможете спокойно спать.
А можно включить "параноидальный" режим предупреждений, и тогда сами авторы языка Керниган с Ричи вряд ли сумели бы написать код без варнингов
Поэтому увидели варнинг - просмотрите код: если на самом деле компилятор прав - устраняйте проблему, если он "перебдел" - живите спокойно. Как правило, всегда можно устранить варнинг правкой кода, но не всегда это дает реально полезный эффект, если не считать за пользу спокойствие компилятора.
- Сообщения: 22
- Зарегистрирован: Сб дек 26, 2015 22:28:05
Форумчане, прошу совет: надо передать в функцию указатель на значение типа char, при том что параметром функции является указатель на тип int. Реализовал с помощью буфера int, копирую туда значение, вызываю функцию, после чего востанавливаю значение с буфера. Какой подход будет более коректным не изменяя тип значения char?
- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Помогите со структурой
Вот нашёл в своих старых записях, решил применить да что то не выходит пишет ошибку, но раньше компилировалось, кажется.
Помогите связать функцию и структуру?
Код: Выделить всё
struct teme {
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.
Поэтому так: либо так:
Потом, 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};
void chitaem(struct time *vremu) {
vremu->eig = vremu->vin + 12;
}Код: Выделить всё
typedef struct {
unsigned int ch;
unsigned int vin;
unsigned int mih;
volatile unsigned int eig;
} time;
time vremu = {10,23,45,0};
void chitaem(time *vremu) {
vremu->eig = vremu->vin + 12;
}- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Спасибо, это просто набор букв, в котором закралась ошибочка.
А как теперь вызывать эту функцию?
А как теперь вызывать эту функцию?
Как обычно, по имени, передавая в аргументах адрес структуры, в которой надо eig = vin + 12 проделать.
- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Т.е.
Нет как то это всё мудрёно, я наверно пойду другим путём
Это просто пример.
Код: Выделить всё
chitaem(&vremu);Код: Выделить всё
void chitaem (unsigned int* eig,unsigned int* vin){
*eig=*vin+12;
}
Вообще, если это vremu (что за странное название, кстати?) одно, то ничто не мешает эту функцию вообще без параметров сделать.
Ну а если не одно - то красивее получается так:
Плюс, если vremu (врему это время?) должно как-то со временем работать, то unsigned int для элементов структуры - это слишком, достатоно и обчного char. Всё-таки на 8бит контроллерах это существенно.
И да, интересно всё же - что скрывается под этими странными именами переменных, странно звучащими в русской транскрипции "врему", "вин", "мих", "еиг"? Просто я, например, когда пишу код, стараюсь какие-то осмысленные имена переменным давать, а тут даже близко непонятно, что это. Интригует, знаете ли.
Ну а если не одно - то красивее получается так:
Код: Выделить всё
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};
void chitaem(time *vr) {
vr->eig = vr->vin + 12;
}
...
chitaem(&vrem0);
...
chitaem(&vrem1);
...
chitaem(&vrem2);
...И да, интересно всё же - что скрывается под этими странными именами переменных, странно звучащими в русской транскрипции "врему", "вин", "мих", "еиг"? Просто я, например, когда пишу код, стараюсь какие-то осмысленные имена переменным давать, а тут даже близко непонятно, что это. Интригует, знаете ли.
- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Да я не могу придумать, какие то подходящие приблизительно по смыслу, ударил по клавиатуре пальцами что получилось то и ладно.
Ага, а потом 
TICLIR писал(а):нашёл в своих старых записях, решил применить да что то не выходит
- Сообщения: 1430
- Зарегистрирован: Вт июн 07, 2011 08:03:18
Вопрос к ARV. хотя, и не только.))
Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании.
Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно.
Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции?
Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании.
Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно.
Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции?
Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Зачем крутить задачу в прерывании? Они не для этого предназначены а для быстрой реакции на внешние события.
Взаимоисключающие параграфы. Быстрой реакции на прерывания при раздутом прерывании не будет. Если только при условии разрешения вложенных прерываний.... и потом разгребать непонятно как работающий индусский код.
В прерывании надо быстро, как пуля, среагировать и вылететь из него. Остальное, что нужно доделать - в основном коде. Если успользуются функции в прерывании - инлайнить их в прерывание.
В прерывании надо быстро, как пуля, среагировать и вылететь из него. Остальное, что нужно доделать - в основном коде. Если успользуются функции в прерывании - инлайнить их в прерывание.
- Сообщения: 1430
- Зарегистрирован: Вт июн 07, 2011 08:03:18
Согласен, не красиво. Но хотелось бы ещё чего то полезного поделать...
А тогда не получается быстро обрабатывать данные получаемые в прерывании...((
А тогда не получается быстро обрабатывать данные получаемые в прерывании...((
А их там надо быстро обрабатывать? Обычно данные надо быстро получить, а разгребать можно потом. Не часто требуется на лету обрабатывать.
В общем, мало исходных данных. Точнее, их совсем нет. Что за данные, что с ними делать..
В общем, мало исходных данных. Точнее, их совсем нет. Что за данные, что с ними делать..
- Сообщения: 1430
- Зарегистрирован: Вт июн 07, 2011 08:03:18
А нет ли возможности принудительно запретить формирование пролога?
Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично?
Инлайн, как я понимаю, не гарантирует инлайн на 100%?
Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично?
Инлайн, как я понимаю, не гарантирует инлайн на 100%?
И разрушить работу всей программы?
Компилятор лучше знает что туда добавлять и если у него не будет повода туда что-то добавлять(код на ассемблере, например), то ничего и не создаст.
Посмотрите дизассемблированный листинг, может там ничего такого и нет страшного.
Инлайнить функции в обработчик прерывания имеет смысл только для очень коротких функций, дальше 20...50 ассемблерных команд функции уже нет смысла инлайнить - выигрыш минимальный а цена слишком большая по сравнению с эффектом.
Компилятор лучше знает что туда добавлять и если у него не будет повода туда что-то добавлять(код на ассемблере, например), то ничего и не создаст.
Посмотрите дизассемблированный листинг, может там ничего такого и нет страшного.
Инлайнить функции в обработчик прерывания имеет смысл только для очень коротких функций, дальше 20...50 ассемблерных команд функции уже нет смысла инлайнить - выигрыш минимальный а цена слишком большая по сравнению с эффектом.
OKF писал(а):Вопрос к ARV. хотя, и не только.))
Нужна быстрая реакция на прерывание. И хотелось что бы вся задача крутилась в прерывании.
Но, т.к. в задаче имеются функции, будет увеличен и пролог, что крайне нежелательно.
Собственно вопрос. Возможно ли что бы прологом/эпилогом были оформлены уже сами функции?
Т.е., что бы этот огромный пролог располагался не с самого начала обработчика?
если хотите, используйте "голый" обработчик прерыванийOKF писал(а):А нет ли возможности принудительно запретить формирование пролога?
Т.е., что бы функции брали на себя эту заботу. Либо "не светить" функции в ISR, что аналогично?
Инлайн, как я понимаю, не гарантирует инлайн на 100%?
Код: Выделить всё
ISR(TIMER0_OVF_vect, ISR_NAKED)если надо, чтобы функция ГАРАНТИРОВАННО инлайнилась, используйте атрибут always_inline
Код: Выделить всё
inline void my_func(void) __attribute__((always_inline)){
//}P.S. кстати, static-функции достаточно неплохо инлайнятся автоматически при включении оптимизиции, особенно, если вызываются из одного места
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!


