|
Косяк у Кейла, Препроцессор не следит за скобками |
|
|
|
Aug 28 2015, 11:21
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Делаю функцию программной задержки. (Длинная не нужна, естественно, но вопрос уже академический, захотел дойти до предела.) Каждый цикл выполняется за 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-битовое вычисление, а меньшее.
|
|
|
|
|
Aug 28 2015, 11:51
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(ViKo @ Aug 28 2015, 16:21)  Как будто у Кейла не 64-битовое вычисление, а меньшее. а если DELAY(50ULL, _SS); ?
|
|
|
|
|
Aug 28 2015, 12:00
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Заменил #define _NS 1ULL #define _US 1000ULL #define _MS 1000000ULL #define _SS 1000000000ULL Вычисляется правильно. Т.е., пока препроцессор не увидит число ULL, он вычисляет в 32 разрядах. Со скобками, похоже, я подметил правильно. Он их игнорирует, если может себе позволить. Цитата(den_po @ Aug 28 2015, 14:51)  а если DELAY(50ULL, _SS); ? Тоже работает. Цитата(aaarrr @ Aug 28 2015, 14:44)  В макросе не хватает скобок для VALUE и UNIT. "Не помогает".
|
|
|
|
|
Aug 28 2015, 12:08
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(ViKo @ Aug 28 2015, 15:00)  "Не помогает". И не должно  Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах: Код MACRO(a + b); MACRO(a ? b : c); Ну и ';' в макросе тоже делать нечего.
|
|
|
|
|
Aug 28 2015, 12:12
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить Код do { \ <тело макроса> \ } while (0)
|
|
|
|
|
Aug 28 2015, 12:13
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(aaarrr @ Aug 28 2015, 15:08)  Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах: В-общем, да. Но в данном примере я всегда буду подавать конкретное число. Цитата Ну и ';' в макросе тоже делать нечего. Аналогично. Заменил макро функцией, которая вызывается конкретно, ничего не возвращает, внутри выражений не участвует. P.S. На Кейл я гнал зря!  P.P.S. Еще добавил константу, чтобы задержка была не меньше требуемой. К единицам измерения добавил суффиксы ULL. Благодать. DelayFourCycles((VALUE * UNIT * (SYSCLK / 1000000) + 3999) / 4000);
|
|
|
|
|
Aug 28 2015, 13:47
|

Частый гость
 
Группа: Участник
Сообщений: 156
Регистрация: 27-09-06
Из: Irkutsk
Пользователь №: 20 747

|
Цитата Сначала любые операнды типа CHAR или SHORT преобразуются в INT, а любые операнды типа FLOAT преобразуются в DOUBLE. Затем, если какой-либо операнд имеет тип DOUBLE, то другой преобразуется к типу DOUBLE, и это будет типом результата. В противном случае, если какой-либо операнд имеет тип LONG, то другой операнд преобразуется к типу LONG, и это и будет типом результата. В противном случае, если какой-либо операнд имеет тип UNSIGNED, то другой операнд преобразуется к типу UNSIGNED, и это будет типом результата. В противном случае оба операнда будут иметь тип INT, и это будет типом результата. Керниган, Ричи. Язык C, гл. 14.6. Арифметические преобразования Учиться никогда не поздно
--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
|
|
|
|
|
Aug 28 2015, 14:46
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (Kabdim @ Aug 28 2015, 15:12)  Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить CODE do { \ <тело макроса> \ } while (0) Сюрприз! Вообще-то именно "\" НУ СОВСЕМ НИКАКОГО отношения не имеет к необходимости использования трюка do{}while(0) Почему - подумайте самостоятельно. Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение QUOTE (Golikov A. @ Aug 28 2015, 17:26)  Это руководство к действию или описание происходящего? Что - то как то странно звучит.... Это K&R, так-что это Ваш вопрос как-то странно звучит
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|