ViKo 1 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Делаю функцию программной задержки. (Длинная не нужна, естественно, но вопрос уже академический, захотел дойти до предела.) Каждый цикл выполняется за 4 такта, отсюда и деление на 4000. Нюансы не интересны, не в этом дело. #define SYSCLK 48000000ULL #define _NS 1 #define _US 1000 #define _MS 1000000 #define _SS 1000000000 #define DELAY(VALUE, UNIT); \ /* DelayFourCycles(VALUE * UNIT * (SYSCLK / 1000000) / 4000); */ \ DelayFourCycles((SYSCLK / 1000000) * VALUE * UNIT / 4000); DELAY(50, _SS); Так вот, когда сделал, как в закомментированной строке, Кейл ругается на то, что число не влазит в int. И загружает в функцию абы что. Если же сделать, как в строке без комментария, то все вычисляется правильно. Выходит, Кейл видит что последовательность операций равнозначна, что со скобками, что без, и лихо их отбрасывает. Возникает переполнение. Хотя не понятно, отчего возникает, 64 битов должно хватать (на компьютерном калькуляторе хватает). Как будто у Кейла не 64-битовое вычисление, а меньшее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба В макросе не хватает скобок для VALUE и UNIT. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Как будто у Кейла не 64-битовое вычисление, а меньшее. а если DELAY(50ULL, _SS); ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Заменил #define _NS 1ULL #define _US 1000ULL #define _MS 1000000ULL #define _SS 1000000000ULL Вычисляется правильно. Т.е., пока препроцессор не увидит число ULL, он вычисляет в 32 разрядах. Со скобками, похоже, я подметил правильно. Он их игнорирует, если может себе позволить. а если DELAY(50ULL, _SS); ? Тоже работает. В макросе не хватает скобок для VALUE и UNIT. "Не помогает". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 28 августа, 2015 Опубликовано 28 августа, 2015 (изменено) · Жалоба Кмк объяснение другое. VALUE * UNIT * (SYSCLK / 1000000) / 4000 1 действие - (SYSCLK / 1000000) ок VALUE * UNIT * temp64_1 / 4000 2 действие: Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит. Т.к. это явные константы, то перемножение выолняет компилятор и закономерно ругается. Были бы это переменные тихо бы переполнялось в рантайме. Правило хорошего тона расширять явно первое значение до желаемого типа. ЗЫ Это поведение, не Кейла, а любимого C. Изменено 28 августа, 2015 пользователем Kabdim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Кмк объяснение другое. ... Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит. Понял. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба "Не помогает". И не должно :) Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах: MACRO(a + b); MACRO(a ? b : c); Ну и ';' в макросе тоже делать нечего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить do { \ <тело макроса> \ } while (0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах: В-общем, да. Но в данном примере я всегда буду подавать конкретное число. Ну и ';' в макросе тоже делать нечего. Аналогично. Заменил макро функцией, которая вызывается конкретно, ничего не возвращает, внутри выражений не участвует. P.S. На Кейл я гнал зря! :laughing: P.P.S. Еще добавил константу, чтобы задержка была не меньше требуемой. К единицам измерения добавил суффиксы ULL. Благодать. DelayFourCycles((VALUE * UNIT * (SYSCLK / 1000000) + 3999) / 4000); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
miheyk 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Сначала любые операнды типа CHAR или SHORT преобразуются в INT, а любые операнды типа FLOAT преобразуются в DOUBLE. Затем, если какой-либо операнд имеет тип DOUBLE, то другой преобразуется к типу DOUBLE, и это будет типом результата. В противном случае, если какой-либо операнд имеет тип LONG, то другой операнд преобразуется к типу LONG, и это и будет типом результата. В противном случае, если какой-либо операнд имеет тип UNSIGNED, то другой операнд преобразуется к типу UNSIGNED, и это будет типом результата. В противном случае оба операнда будут иметь тип INT, и это будет типом результата. Керниган, Ричи. Язык C, гл. 14.6. Арифметические преобразования Учиться никогда не поздно :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Сначала любые операнды типа CHAR или SHORT преобразуются в INT, а любые операнды типа FLOAT преобразуются в DOUBLE. Это руководство к действию или описание происходящего? Что - то как то странно звучит.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить do { \ <тело макроса> \ } while (0) Сюрприз! Вообще-то именно "\" НУ СОВСЕМ НИКАКОГО отношения не имеет к необходимости использования трюка do{}while(0) Почему - подумайте самостоятельно. Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение :( Это руководство к действию или описание происходящего? Что - то как то странно звучит.... Это K&R, так-что это Ваш вопрос как-то странно звучит :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение :( В чем состоит принципиальная ошибка? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба В чем состоит принципиальная ошибка? В бессмысленности получившегося выражения. По этой причине прилично-бы выдать warning. IAR-у можно включить. Но у большинства - нет :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 28 августа, 2015 Опубликовано 28 августа, 2015 · Жалоба В бессмысленности получившегося выражения. По этой причине прилично-бы выдать warning. IAR-у можно включить. Но у большинства - нет :( Видимо, компиляторостроители должны дать возможность отключать подобные предупреждения только для макросов. Потому что макросы побуждают к творчеству креативных макросописателей, и у них часто получается что-то интересное и полезное. И я не стану спешить осуждать их за "бессмыссленность" чего-то там. Так что мяч на стороне компиляторостроителей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться