реклама на сайте
подробности

 
 
18 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Косяк у Кейла, Препроцессор не следит за скобками
ViKo
сообщение Aug 28 2015, 11:21
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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-битовое вычисление, а меньшее.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 28 2015, 11:44
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



В макросе не хватает скобок для VALUE и UNIT.
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 28 2015, 11:51
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Цитата(ViKo @ Aug 28 2015, 16:21) *
Как будто у Кейла не 64-битовое вычисление, а меньшее.

а если DELAY(50ULL, _SS); ?
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 12:00
Сообщение #4


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 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.

"Не помогает".
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 28 2015, 12:01
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Кмк объяснение другое.
VALUE * UNIT * (SYSCLK / 1000000) / 4000
1 действие - (SYSCLK / 1000000) ок
VALUE * UNIT * temp64_1 / 4000
2 действие:
Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит. Т.к. это явные константы, то перемножение выолняет компилятор и закономерно ругается. Были бы это переменные тихо бы переполнялось в рантайме.
Правило хорошего тона расширять явно первое значение до желаемого типа.
ЗЫ Это поведение, не Кейла, а любимого C.

Сообщение отредактировал Kabdim - Aug 28 2015, 12:02
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 12:04
Сообщение #6


Универсальный солдатик
******

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



Цитата(Kabdim @ Aug 28 2015, 15:01) *
Кмк объяснение другое.
...
Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит.

Понял. Спасибо!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 28 2015, 12:08
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ViKo @ Aug 28 2015, 15:00) *
"Не помогает".

И не должно sm.gif

Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах:
Код
MACRO(a + b);
MACRO(a ? b : c);


Ну и ';' в макросе тоже делать нечего.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 28 2015, 12:12
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить
Код
do { \
<тело макроса> \
} while (0)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 28 2015, 12:13
Сообщение #9


Универсальный солдатик
******

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



Цитата(aaarrr @ Aug 28 2015, 15:08) *
Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах:

В-общем, да. Но в данном примере я всегда буду подавать конкретное число.
Цитата
Ну и ';' в макросе тоже делать нечего.

Аналогично. Заменил макро функцией, которая вызывается конкретно, ничего не возвращает, внутри выражений не участвует.

P.S. На Кейл я гнал зря! laughing.gif

P.P.S. Еще добавил константу, чтобы задержка была не меньше требуемой. К единицам измерения добавил суффиксы ULL. Благодать.
DelayFourCycles((VALUE * UNIT * (SYSCLK / 1000000) + 3999) / 4000);
Go to the top of the page
 
+Quote Post
Mihey_K
сообщение Aug 28 2015, 13:47
Сообщение #10


Частый гость
**

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



Цитата
Сначала любые операнды типа CHAR или SHORT преобразуются в
INT, а любые операнды типа FLOAT преобразуются в DOUBLE.
Затем, если какой-либо операнд имеет тип DOUBLE, то другой
преобразуется к типу DOUBLE, и это будет типом результата.
В противном случае, если какой-либо операнд имеет тип LONG,
то другой операнд преобразуется к типу LONG, и это и будет
типом результата.
В противном случае, если какой-либо операнд имеет тип
UNSIGNED, то другой операнд преобразуется к типу UNSIGNED,
и это будет типом результата.
В противном случае оба операнда будут иметь тип INT, и это
будет типом результата.
Керниган, Ричи. Язык C, гл. 14.6. Арифметические преобразования
Учиться никогда не поздно sm.gif


--------------------
Блог о разработке на CC430, SIM900, GPS, ARM и не только...
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 28 2015, 14:26
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Цитата
Сначала любые операнды типа CHAR или SHORT преобразуются в
INT, а любые операнды типа FLOAT преобразуются в DOUBLE.

Это руководство к действию или описание происходящего?
Что - то как то странно звучит....
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 28 2015, 14:46
Сообщение #12


Гуру
******

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



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

Сюрприз!
Вообще-то именно "\" НУ СОВСЕМ НИКАКОГО отношения не имеет к необходимости использования трюка do{}while(0)
Почему - подумайте самостоятельно.
Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение sad.gif



QUOTE (Golikov A. @ Aug 28 2015, 17:26) *
Это руководство к действию или описание происходящего?
Что - то как то странно звучит....

Это K&R, так-что это Ваш вопрос как-то странно звучит sm.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 28 2015, 14:57
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(zltigo @ Aug 28 2015, 17:46) *
Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение sad.gif

В чем состоит принципиальная ошибка?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 28 2015, 15:02
Сообщение #14


Гуру
******

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



QUOTE (aaarrr @ Aug 28 2015, 17:57) *
В чем состоит принципиальная ошибка?

В бессмысленности получившегося выражения. По этой причине прилично-бы выдать warning. IAR-у можно включить. Но у большинства - нет sad.gif



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 28 2015, 15:13
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(zltigo @ Aug 28 2015, 18:02) *
В бессмысленности получившегося выражения. По этой причине прилично-бы выдать warning. IAR-у можно включить. Но у большинства - нет sad.gif

Видимо, компиляторостроители должны дать возможность отключать подобные предупреждения только для макросов. Потому что макросы побуждают к творчеству креативных макросописателей, и у них часто получается что-то интересное и полезное. И я не стану спешить осуждать их за "бессмыссленность" чего-то там. Так что мяч на стороне компиляторостроителей.
Go to the top of the page
 
+Quote Post

18 страниц V   1 2 3 > » 
Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 18:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016