NewMaestro 0 21 января, 2009 Опубликовано 21 января, 2009 · Жалоба Не могу врубится в чем проблема. IAR 5.11. ATmega168 В h-файле объявлены константы: #define CONST1 8640 #define CONST2 720 В С-файле функция вида: void func(void) { static unsigned short w, x; w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1); } w вычисляется не верно. Проверял операцию по действиям: CONST1 * x вычисляется верно, а вот деление уже возвращает фигню. Что поразительно, начинает считать верно, когда вместо CONST2 подставляю в код ее реальное значение 720: w = (unsigned short)((unsigned long)CONST1 * x / 720 + 1); Это работает. В чем прикол? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BOS 1 21 января, 2009 Опубликовано 21 января, 2009 · Жалоба Не могу врубится в чем проблема. IAR 5.11. ATmega168 В h-файле объявлены константы: .... В чем прикол? А "прикол" в том, что по умолчаннию константам CONST1 и CONST2 компилятором оределяется их размер как int (применительно к IAR AVR 5.11 - 4 байта). Тоесть максимальное возможное число 65535. А приведение к нужному типу происходит, когда непосредственно выполяется операция деления, как вы и указали это сделать. Поэтому лучше привести константы к нужному размеру исходя из возможной получаемой длины результата и его знака. Я бы указал :rolleyes: : #define CONST1 8640UL #define CONST2 720UL Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NewMaestro 0 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Я бы указал :rolleyes: : #define CONST1 8640UL #define CONST2 720UL Верно. Так работает. Но только есть одно Но. На самом деле моя константа определяется не числом а выражением также состоящим из констант. И как только я подставлю вычесленный результат-константу в выражение в функции - тут же облом. Но если присвоить эту коснтанту переменной, и использовать в выражении переменную - то тоже все ок. Неужели без введения переменной нельзя обойтись. В Выражениях с константами я уже пробовал и приведение типов делать и UL подставлять - нифига! Работает только если в лоб число - например 720UL. А в выражении забивает компилер на этот UL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Johnny81 0 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Что то тут не то. Куски #define CONST2 720 w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1); и w = (unsigned short)((unsigned long)CONST1 * x / 720 + 1); должны быть абсолютно эквивалентны - транслироваться в одинаковый asm-код. А судя по вашим словам это не так. Что поразительно, начинает считать верно, когда вместо CONST2 подставляю в код ее реальное значение 720: Попробуйте включить генерацию lst - файлов и сравнить результат в обоих случаях... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BOS 1 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Верно. Так работает. Так работает или не работает ? Вы пожалуйста определитесь ! На самом деле моя константа определяется не числом а выражением также состоящим из констант. Насколько я вижу из вашего кода, выражение о котором Вы упоминаете w = (unsigned short)((unsigned long)CONST1 * x / CONST2 + 1); никак не может быть константным, поскольку в нем присутвует переменная unsigned short x. Дело в том что нужно понимать, что если выраженние состоит из констант тоесть по сути является константным для программы, то его результат получает препроцессор перед компиляцией, а когда выражение не является константным, то его результат вычисляется уже в процессе выполнения самой программы. В таких случаях, возможно даже придется подключать библиотеку математических функций. Или Вы думаете ATmega168 имеет в наборе команд ассемблера операции деления ? В любом случае - определитесь для начала c выражением в котором Вы выполняеете вычисления, потом в размере и знаке каждого значения выражения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба Но. На самом деле моя константа определяется не числом а выражением также состоящим из констант. 1. Возможно, выражение в define при CONST2 записано не корректно. Попробуйте определить чему будет равно A=CONST2 2. Попробуйте: либо запишите #define CONST2 ((unsigned long)(выражение)) либо w = (unsigned short)((unsigned long)CONST1 * x / (unsigned long)CONST2 + 1); P.S. Еще бывает, что выражение в дефайне не берут в скобки - тогда получаются чудеса (например, если выражение типа A + B ). Очень желательно записывать так: #define CONST2 (выражение) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NewMaestro 0 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба P.S. Еще бывает, что выражение в дефайне не берут в скобки - тогда получаются чудеса (например, если выражение типа A + B ). Очень желательно записывать так: #define CONST2 (выражение) Палыч, Вы монстр! Вы точно поймали суть, хотя вопрос я изначально поставил не корректно, не указав, что в дефайне стоит выражение, а не число. Спасибо за правильный ответ! Я целый день тупил с этим, а все дело оказалось просто в скобках. А я-то думал, что define на этапе компиляции вычисляется, а потом подставляется в выражение. А оказалось, что он сначала подставляеся в выражение, затем расставляются приоритеты операций, и потом только вычисляется. Без скобок приоритеты-то неверно расставлялись... :-) Спасибо. Вопрос снят! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 16 22 января, 2009 Опубликовано 22 января, 2009 · Жалоба А я-то думал, что define на этапе компиляции вычисляется, а потом подставляется в выражение. Нет, он подставляется препроцессором перед компиляцией, причём тупо 1-в-1 , за исключением макросов с параметрами Теперь вы знаете, зачем в дефайнах ставят скобки :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться