Перейти к содержанию
    

Делаю функцию программной задержки. (Длинная не нужна, естественно, но вопрос уже академический, захотел дойти до предела.) Каждый цикл выполняется за 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-битовое вычисление, а меньшее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как будто у Кейла не 64-битовое вычисление, а меньшее.

а если DELAY(50ULL, _SS); ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заменил

#define _NS 1ULL

#define _US 1000ULL

#define _MS 1000000ULL

#define _SS 1000000000ULL

Вычисляется правильно. Т.е., пока препроцессор не увидит число ULL, он вычисляет в 32 разрядах.

Со скобками, похоже, я подметил правильно. Он их игнорирует, если может себе позволить.

 

а если DELAY(50ULL, _SS); ?

Тоже работает.

 

В макросе не хватает скобок для VALUE и UNIT.

"Не помогает".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кмк объяснение другое.

VALUE * UNIT * (SYSCLK / 1000000) / 4000

1 действие - (SYSCLK / 1000000) ок

VALUE * UNIT * temp64_1 / 4000

2 действие:

Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит. Т.к. это явные константы, то перемножение выолняет компилятор и закономерно ругается. Были бы это переменные тихо бы переполнялось в рантайме.

Правило хорошего тона расширять явно первое значение до желаемого типа.

ЗЫ Это поведение, не Кейла, а любимого C.

Изменено пользователем Kabdim

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кмк объяснение другое.

...

Операции выплняются по очереди, т.е. умножение двух int друг на друга и т.к. они оба int то никакого неявного расширяющего преобразования не происходит.

Понял. Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"Не помогает".

И не должно :)

 

Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах:

MACRO(a + b);
MACRO(a ? b : c);

 

Ну и ';' в макросе тоже делать нечего.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить

do { \
<тело макроса> \
} while (0)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах:

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

Ну и ';' в макросе тоже делать нечего.

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

 

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

 

P.P.S. Еще добавил константу, чтобы задержка была не меньше требуемой. К единицам измерения добавил суффиксы ULL. Благодать.

DelayFourCycles((VALUE * UNIT * (SYSCLK / 1000000) + 3999) / 4000);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сначала любые операнды типа CHAR или SHORT преобразуются в

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

Затем, если какой-либо операнд имеет тип DOUBLE, то другой

преобразуется к типу DOUBLE, и это будет типом результата.

В противном случае, если какой-либо операнд имеет тип LONG,

то другой операнд преобразуется к типу LONG, и это и будет

типом результата.

В противном случае, если какой-либо операнд имеет тип

UNSIGNED, то другой операнд преобразуется к типу UNSIGNED,

и это будет типом результата.

В противном случае оба операнда будут иметь тип INT, и это

будет типом результата.

Керниган, Ричи. Язык C, гл. 14.6. Арифметические преобразования

Учиться никогда не поздно :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сначала любые операнды типа CHAR или SHORT преобразуются в

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

Это руководство к действию или описание происходящего?

Что - то как то странно звучит....

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить

do { \
<тело макроса> \
} while (0)

Сюрприз!

Вообще-то именно "\" НУ СОВСЕМ НИКАКОГО отношения не имеет к необходимости использования трюка do{}while(0)

Почему - подумайте самостоятельно.

Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение :(

 

 

 

Это руководство к действию или описание происходящего?

Что - то как то странно звучит....

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение :(

В чем состоит принципиальная ошибка?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В чем состоит принципиальная ошибка?

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Видимо, компиляторостроители должны дать возможность отключать подобные предупреждения только для макросов. Потому что макросы побуждают к творчеству креативных макросописателей, и у них часто получается что-то интересное и полезное. И я не стану спешить осуждать их за "бессмыссленность" чего-то там. Так что мяч на стороне компиляторостроителей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...