Jump to content
    

Косяк у Кейла

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Заменил

#define _NS 1ULL

#define _US 1000ULL

#define _MS 1000000ULL

#define _SS 1000000000ULL

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

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

 

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

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

 

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

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

Share this post


Link to post
Share on other sites

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

VALUE * UNIT * (SYSCLK / 1000000) / 4000

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

VALUE * UNIT * temp64_1 / 4000

2 действие:

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

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

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

Edited by Kabdim

Share this post


Link to post
Share on other sites

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

...

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

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

Share this post


Link to post
Share on other sites

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

И не должно :)

 

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

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

 

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

 

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

 

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

 

Share this post


Link to post
Share on other sites

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

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

Сюрприз!

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

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

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

 

 

 

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

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

 

 

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...