Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Косяк у Кейла
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3, 4, 5, 6
ViKo
Делаю функцию программной задержки. (Длинная не нужна, естественно, но вопрос уже академический, захотел дойти до предела.) Каждый цикл выполняется за 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
В макросе не хватает скобок для VALUE и UNIT.
den_po
Цитата(ViKo @ Aug 28 2015, 16:21) *
Как будто у Кейла не 64-битовое вычисление, а меньшее.

а если DELAY(50ULL, _SS); ?
ViKo
Заменил
#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.

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

Понял. Спасибо!
aaarrr
Цитата(ViKo @ Aug 28 2015, 15:00) *
"Не помогает".

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

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


Ну и ';' в макросе тоже делать нечего.
Kabdim
Если говорить про стиль макрописания. То как только в макросе возникает символ "\" руки должны автоматически выводить
Код
do { \
<тело макроса> \
} while (0)
ViKo
Цитата(aaarrr @ Aug 28 2015, 15:08) *
Просто так макросы не стоит писать, а то потом замучаетесь искать глюки при вызовах:

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

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

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

P.P.S. Еще добавил константу, чтобы задержка была не меньше требуемой. К единицам измерения добавил суффиксы ULL. Благодать.
DelayFourCycles((VALUE * UNIT * (SYSCLK / 1000000) + 3999) / 4000);
Mihey_K
Цитата
Сначала любые операнды типа CHAR или SHORT преобразуются в
INT, а любые операнды типа FLOAT преобразуются в DOUBLE.
Затем, если какой-либо операнд имеет тип DOUBLE, то другой
преобразуется к типу DOUBLE, и это будет типом результата.
В противном случае, если какой-либо операнд имеет тип LONG,
то другой операнд преобразуется к типу LONG, и это и будет
типом результата.
В противном случае, если какой-либо операнд имеет тип
UNSIGNED, то другой операнд преобразуется к типу UNSIGNED,
и это будет типом результата.
В противном случае оба операнда будут иметь тип INT, и это
будет типом результата.
Керниган, Ричи. Язык C, гл. 14.6. Арифметические преобразования
Учиться никогда не поздно sm.gif
Golikov A.
Цитата
Сначала любые операнды типа CHAR или SHORT преобразуются в
INT, а любые операнды типа FLOAT преобразуются в DOUBLE.

Это руководство к действию или описание происходящего?
Что - то как то странно звучит....
zltigo
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
aaarrr
Цитата(zltigo @ Aug 28 2015, 17:46) *
Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение sad.gif

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

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

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

Видимо, компиляторостроители должны дать возможность отключать подобные предупреждения только для макросов. Потому что макросы побуждают к творчеству креативных макросописателей, и у них часто получается что-то интересное и полезное. И я не стану спешить осуждать их за "бессмыссленность" чего-то там. Так что мяч на стороне компиляторостроителей.
Kabdim
Огласите пожалуйста решение лучше. Думаю многим было бы интересно на него посмотреть.
aaarrr
Бессмысленной можно было бы признать запись while(0) {...} - тут warning был бы вполне уместен, но в случае do {...} while(0) одна итерация будет выполнена, так что смысл остается (пусть только для помянутой обертки от макроса).
Mihey_K
Сам по себе цикл с единичной итерацией да, бесмыслица. Но GCC молча делает дело. Про обрамление в ду вайл могу сказать на примере ядра linux - там почти все макросы с переносом строки, но в цикле - единицы, а вот инлайнов вагон. Пожалуй, ду вайл актуален лишь при включении в макрос ветвлений.
zltigo
QUOTE (Kabdim @ Aug 28 2015, 18:16) *
Огласите пожалуйста решение лучше. Думаю многим было бы интересно на него посмотреть.

Давайте все-же по порядку. То, что глупость про "\" написали поняли?


QUOTE (aaarrr @ Aug 28 2015, 18:18) *
Бессмысленной можно было бы признать запись while(0) {...} - тут warning был бы вполне уместен

Бессмысленнен любой с константой.
QUOTE
в случае do {...} while(0) одна итерация будет выполнена, так что смысл остается (пусть только для помянутой обертки от макроса).

Нет смысла и в этом, ибо для одной итерации достаточно {....}
Так-что весь этот трюк из-за ";" и не для чего более.

QUOTE (Mihey_K @ Aug 28 2015, 18:21) *
там почти все макросы переносом строки,

Да не имеет никкакого отношения склеивание строк к причинам использования этого трюка. ЛЮБОЙ макрос содержащий БОЛЕЕ одного выражения, хоть в одной строке, хоть в 999,
проблематичен при использовании типа такого:
if( )
MACRO();

Посему либо следить за тем, что-бы:
if()
{
MACRO();
}
либо трюк использовать,

Либо только {}, но тогда так
if()
MACRO()
ViKo
Цитата(scifi @ Aug 28 2015, 16:01) *
Почему-то думал, что ViKo - бывалый. А он в таких азах плавает laughing.gif

Думал, раз первое действие - с ULL числами, то препроцессор "запомнит", с чем имеет дело. А дальше искал, где же оно переполняется.
Golikov A.
вообще то, насколько я помню трюк
do
while(0)
создан для того чтобы в теле можно было в любой момент поставить break или continue и вывалиться из цикла, то есть закончить кусок кода без применения нелюбимого и кое где запрещенного оператора goto. Интересное использование в качестве превращение группы операторов в один, чтобы он под условие влезал без скобок...

символ переноса строки используется для переноса строки без ее разрыва. Дефайн требует объявление в 1 строку, а от этого падает читаемость. Но думая про то что много строк - это обычно надо для множества операторов, то может правило все пихать сразу под ду-вайл(0) для универсальности макроса может и имеет смысл....

while(1), while(0) имеет тот же смысл что описан в стандарте, никаких конструкций и правил он не нарушает, потому имеет право на жизнь и использование в тексте, ровно как и
for(;;). Наличие или отсутствие варнинга - это на усмотрение среды, ибо любые варнинги - это предупреждения от пользователя о возможных ошибках. И тут нет вопроса забили или не забили. Просто все посчитали что доставать пользователя таким варнингом излишне...
aaarrr
Цитата(zltigo @ Aug 28 2015, 19:17) *
Бессмысленнен любой с константой.

Тогда и любимый Вами for(;;) столь же бессмысленнен, т.к. по сути цикл с константой в управляющем выражении.
scifi
Цитата(ViKo @ Aug 28 2015, 20:09) *
Думал, раз первое действие - с ULL числами, то препроцессор "запомнит", с чем имеет дело. А дальше искал, где же оно переполняется.

Только препроцессор тут ни при чём. Препроцессор считает только тогда, когда ему нужно вычислить условие #if. А здесь считает компилятор.

Цитата(aaarrr @ Aug 28 2015, 20:31) *
Тогда и любимый Вами for(;;) столь же бессмысленнен, т.к. по сути цикл с константой в управляющем выражении.

Да это вообще абракадабра. Во всяком случае, любой вменяемый человек понимает, что "while (1)" - это "пока всегда", и по ошибке такое не напишет никто. Так что аргумент с предупреждениями компилятора притянут за все места. Хотя я сам пишу "for (;;)", но это дело вкуса...
aaarrr
Цитата(scifi @ Aug 28 2015, 20:39) *
Да это вообще абракадабра. Во всяком случае, любой вменяемый человек понимает, что "while (1)" - это "пока всегда", и по ошибке такое не напишет никто. Так что аргумент с предупреждениями компилятора притянут за все места. Хотя я сам пишу "for (;;)", но это дело вкуса...

Именно. Управляющее выражение может быть константой (явной или неявной). Все это - while(1) {}, for(;;) {}, do {} while(0) - нормальные и однозначно трактуемые языковые конструкции.
ViKo
напишите for ( ; true; ), если пустота не нравится. rolleyes.gif
Golikov A.
Цитата
Сначала любые операнды типа CHAR или SHORT преобразуются в
INT, а любые операнды типа FLOAT преобразуются в DOUBLE.


а в стандарте

Цитата
First, if the corresponding real type of either operand is long double, the other
operand is converted, without change of type domain, to a type whose
corresponding real type is long double.

Otherwise, if the corresponding real type of either operand is double, the other
operand is converted, without change of type domain, to a type whose
corresponding real type is double.

Otherwise, if the corresponding real type of either operand is float, the other
operand is converted, without change of type domain, to a type whose
corresponding real type is float.


то есть я не вижу обязательного перевода в даблу всегда. Более того
float a;
float b;
float c = a + b;
я всегда считал что оно во флотах будет считаться, а не в даблах, а если любой операнд сначала перейдет в даблы
то даже написав (float)a + (float)b мы все равно получаем даблы, и следовательно долгий счет....
так что K&R G&A D&F и что-бы они ни было, по мне оно звучит странно.... я в чем то не прав?
zltigo
QUOTE (aaarrr @ Aug 28 2015, 20:31) *
Тогда и любимый Вами for(;;) столь же бессмысленнен, т.к. по сути цикл с константой в управляющем выражении.

АБСОЛЮТНО адекватное выражение и по этой причине является официально-страндартым вариантом для бесконечного цикла.
Это есть цикл без проверки условия, а не цикл с проверкой того, что измениться не может.
Неадекватным оно было-бы в виде for( ; 1 ; )



QUOTE (aaarrr @ Aug 28 2015, 20:51) *
Именно. Управляющее выражение может быть константой (явной или неявной). Все это - while(1) {}, for(;;) {}, do {} while(0) - нормальные и однозначно трактуемые языковые конструкции.

1 и 3 НЕТ. Вменяемые компиляторы выдают warnig именно по причине того, что константное "управляющее выражение" бессмысленно. Отключаемый, но warning.
aaarrr
Цитата(zltigo @ Aug 28 2015, 21:03) *
Это есть цикл без проверки условия, а не цикл с проверкой того, что измениться не может.

Да ну! А в стандарте написано, что опущенное управляющее выражение заменяется ненулевой константой:
Цитата
An omittedexpression-2is replaced by a nonzero constant.


То есть неявно превращается в "цикл с проверкой того, что измениться не может".
zltigo
QUOTE (scifi @ Aug 28 2015, 20:39) *
Да это вообще абракадабра.

С точностью до наоборот. Просто всякие безграмотные while(1), увы, слишком распространились.
Golikov A.
вот я знаю пример явно ошибочного выражения

Код
int a = 10;
int b = 20;
int MaxFromAandB;
if(a >b);
  MaxFromAandB = a;
else
  MaxFromAandB = b;


if(a >b);

тут и ошибка будет на else без if , и первый if явно зря за точка запятачен.... а обсуждаемые while(1), while(0) - это нормально
zltigo
QUOTE (aaarrr @ Aug 28 2015, 21:06) *
Да ну! А в стандарте написано, что опущенное управляющее выражение заменяется ненулевой константой

Да, это описано ПОВЕДЕНИЕ компилятора. Но когда компилятор видит, что в результате выражения ЕМУ ПЕРЕДАННОГО получается константа, это однозначно тревожный факт указывающий, как минимум на потенциальную ошибку программиста.
Kabdim
Цитата(zltigo @ Aug 28 2015, 20:17) *
Давайте все-же по порядку. То, что глупость про "\" написали поняли?

Согласен исключительно по порядку. Вы воспользовались возможностью указать на формальную неправоту. Согласен конечно.

Цитата(zltigo @ Aug 28 2015, 20:17) *
Бессмысленнен любой с константой.

Не могу сказать что я большой знаток стандарта C, но смутно помню что в стандарте есть определения undefined, unspecified, а вот "бессмысленного" не помню. Не могли бы вы указать где в стандарте говорится о том что цикл с константой бессмыслен?

Цитата(zltigo @ Aug 28 2015, 20:17) *
Нет смысла и в этом, ибо для одной итерации достаточно {....}
Так-что весь этот трюк из-за ";" и не для чего более.

Так подождите, есть всё таки оказывается смысл?

Ну и напомню. В прошлом своём посте я попросил привести полноценную замену "бессмысленной" конструкции. Как вы верно подметили "{...}" на полноценную замену не годится.
zltigo
QUOTE (Kabdim @ Aug 28 2015, 21:20) *
Не могли бы вы указать где в стандарте говорится о том что цикл с константой бессмыслен?

А давайте от обратного. В стандарте описаны ИМЕЮЩИЕ смысл синтаксические конструкции. Для do и while в constant expression НЕ упоминаются. Так-же в стандарте НЕ упомиается, что выражения на русском матерном с точки зрения компилятора бессмысленны. Означает-ли это, что их можно использовать и тоебовать от компилятора их понимания?
QUOTE
Ну и напомню. В прошлом своём посте я попросил привести полноценную замену "бессмысленной" конструкции. Как вы верно подметили "{...}" на полноценную замену не годится.

Полноценной заметой является ИСПОЛЬЗОВАНИЕ фигурных скобок при ВЫЗОВЕ макроса. И в том числе по этой причине, кстати, и существует старое правило магросы большими буквами именовать. Ну а do{ }while(0) есть трюк. Обычный трюк, не всегда переносимый трюк, коих наизобретено множество.

aaarrr
Цитата(zltigo @ Aug 28 2015, 21:12) *
Да, это описано ПОВЕДЕНИЕ компилятора. Но когда компилятор видит, что в результате выражения ЕМУ ПЕРЕДАННОГО получается константа, это однозначно тревожный факт указывающий, как минимум на потенциальную ошибку программиста.

Это справедливо, например, для такого случая:
Код
unsigned int e;
...
if(e >= 0)
{
}

Тут вменяемые компиляторы дают предупреждение.

Но подозревать потенциальную ошибку в while(0) или while(1) как-то странно.
Golikov A.
вот while(0) уже не интересно, а тезис что при вычислении всегда все float преобразуются в double меня заинтересовал. И я не нашел подтверждения в стандарте...
zltigo
QUOTE (aaarrr @ Aug 28 2015, 21:41) *
Но подозревать потенциальную ошибку в while(0) или while(1) как-то странно.

Ну интеллект компиляторов, конечно растет семимильными шагами и можно многое требовать от них. Но все-же надо прежде всего говорить об ОБЩИХ минимальных требованиях описаных стандартом. А там, даже специально посмотрел C11 sm.gif - такого требования не было и нет. Кроме того собственно компилятор НЕ знает, что в исходнике написано while( 1 ) - он получает после препроцессора текст, а там могло быть написано и while( EPRST - eklmn() + 1 ) Тут можно уже подозревать ошибку, или?
Petka
Цитата(zltigo @ Aug 28 2015, 17:46) *
....
Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности большинство компиляторописателей забили на предупреждение sad.gif
....

Что-то задело меня это безапелляционное утверждение.

Для Си-программистов встраиваемых систем группа "энтузиастов" из индустрии разработала стандарт "MISRA C".
Приведу небольшую выдержку из стандарта редакции 2004 года.

Цитата
Rule 19.4 (required): C macros shall only expand to a braced initialiser, a constant,
a string literal, a parenthesised expression, a type qualifier, a
storage class specifier, or a do-while-zero construct.
[Koenig 82–84]
These are the only permitted uses of macros. Storage class specifiers and type qualifiers include
keywords such as extern, static and const. Any other use of #define could lead to unexpected
behaviour when substitution is made, or to very hard-to-read code.
In particular macros shall not be used to define statements or parts of statements except the use
of the do-while construct. Nor shall macros redefine the syntax of the language. All brackets of
whatever type ( ) { } [ ] in the macro replacement list shall be balanced.
The do-while-zero construct (see example below) is the only permitted mechanism for having
complete statements in a macro body. The do-while-zero construct is used to wrap a series of one
or more statements and ensure correct behaviour. Note: the semicolon must be omitted from the
end of the macro body.
For example:
Код
/* The following are compliant */
#define PI 3.14159F /* Constant */
#define XSTAL 10000000 /* Constant */
#define CLOCK (XSTAL/16) /* Constant expression */
#define PLUS2(X) ((X) + 2) /* Macro expanding to expression */
#define STOR extern /* storage class specifier */
#define INIT(value){ (value), 0, 0} /* braced initialiser */
#define CAT (PI) /* parenthesised expression */
#define FILE_A "filename.h" /* string literal */
#define READ_TIME_32() \
do { \
    DISABLE_INTERRUPTS (); \
    time_now = (uint32_t)TIMER_HI << 16; \
    time_now = time_now | (uint32_t)TIMER_LO; \
    ENABLE_INTERRUPTS (); \
} while (0) /* example of do-while-zero */
/* the following are NOT compliant */
#define int32_t long /* use typedef instead */
#define STARTIF if( /* unbalanced () and language redefinition */
#define CAT PI /* non-parenthesised expression */


Так что если заниматься программированием для встраиваемых систем, такая нотация макросов является не только "допустимой", но и обязательной (с точки зрения MISRA C).
Kabdim
Демагогия в техническом споре... свежо! И легко опровергаемо. cool.gif

Цитата(zltigo @ Aug 28 2015, 22:36) *
А давайте от обратного. В стандарте описаны ИМЕЮЩИЕ смысл синтаксические конструкции. Для do и while в constant expression НЕ упоминаются. Так-же в стандарте НЕ упомиается, что выражения на русском матерном с точки зрения компилятора бессмысленны. Означает-ли это, что их можно использовать и тоебовать от компилятора их понимания?

Для do и while зато упоминаются expression. А constant expression частный случай expression.
Список допустимых символов для идентификаторов вполне прописан. Более того, если память меня не подводит, задекларирована максимальна длинна идентификатора. Так что требовать вы конечно можете, но исключительно для забавы. И придется освоить технику малолетних шкетов и выводить "<удалил транслит>" и тому подобное в рамках осмысленного по стандарту набора символов.


Цитата(zltigo @ Aug 28 2015, 22:36) *
Полноценной заметой является ИСПОЛЬЗОВАНИЕ фигурных скобок при ВЫЗОВЕ макроса. И в том числе по этой причине, кстати, и существует старое правило магросы большими буквами именовать. Ну а do{ }while(0) есть трюк. Обычный трюк, не всегда переносимый трюк, коих наизобретено множество.

Ну я так понимаю что ответа по существу дождаться не получится. Но с другой стороны вы дали новую интересную тему. Уточните пожалуйста на какие платформы этот трюк непереносим? Это ведь значит что "грязный трюк" не соответствует стандарту?
zltigo
QUOTE (Petka @ Aug 28 2015, 21:51) *
Так что если заниматься программированием для встраиваемых систем, такая нотация макросов является не только "допустимой", но и обязательной (с точки зрения MISRA C).

Это просто борьба с потенциальной ошибкой, котороая ДЕЙСТВИТЕЛЬНО имеет очень большую вероятность быть сделанной. Вот по этой причине и пошли на соглащение, что тут уж все способы хороши.
scifi
Цитата(zltigo @ Aug 28 2015, 21:50) *
Ну интеллект компиляторов, конечно растет семимильными шагами и можно многое требовать от них.

Да!

Цитата(zltigo @ Aug 28 2015, 21:50) *
Кроме того собственно компилятор НЕ знает, что в исходнике написано while( 1 ) - он получает после препроцессора текст, а там могло быть написано и while( EPRST - eklmn() + 1 ) Тут можно уже подозревать ошибку, или?

Нет!
Я вас умоляю! Что за бред? Это же не квадратура круга. Исходник есть, а компилятор не знает, что в нём? Если компиляторописатель не смог разрулить эту проблему, то он двоечник. Нормальному студенту-второкурснику это под силу.
Блин, я негодую crying.gif
aaarrr
Цитата(zltigo @ Aug 28 2015, 21:50) *
...компилятор НЕ знает, что в исходнике написано while( 1 ) - он получает после препроцессора текст, а там могло быть написано и while( EPRST - eklmn() + 1 ) Тут можно уже подозревать ошибку, или?

Препроцессором можно и черное в белое превратить при желании.
Petka
Цитата(zltigo @ Aug 28 2015, 21:55) *
Это просто борьба с потенциальной ошибкой, котороая ДЕЙСТВИТЕЛЬНО имеет очень большую вероятность быть сделанной. Вот по этой причине и пошли на соглащение, что тут уж все способы хороши.

1) С точки зрения стандарта Си конструкция do-while-zero не является "Implementation-Defined Behavior", "Undefined behavior" или пр. Так что поводов "давать по рукам" программисту никаких нет.
2) Уважаемый Вами инструмент от "IAR Systems" имеет возможность проверять в том числе и правила "MISRA C". Было бы забавно наблюдать что на единственно возможную конструкцию согласно правилам "MISRA C" транслятор при проверке будет выдавать предупреждение. smile3046.gif
aaarrr
Цитата(Golikov A. @ Aug 28 2015, 21:01) *
я всегда считал что оно во флотах будет считаться, а не в даблах, а если любой операнд сначала перейдет в даблы
то даже написав (float)a + (float)b мы все равно получаем даблы, и следовательно долгий счет....
так что K&R G&A D&F и что-бы они ни было, по мне оно звучит странно.... я в чем то не прав?

Все правильно: действующий стандарт отличается от того, что описан у K&R в старой редакции.
Нужно только помнить, что константы все равно по умолчанию интерпретируются как double, т.е. 1.234 - это double, а 1.234F - float.
zltigo
QUOTE (scifi @ Aug 28 2015, 21:58) *
Я вас умоляю! Что за бред?
Блин, я негодую crying.gif

Увы, это совершеная реальность - ПЕРЕД компиляцией сишный исходник проходит через препроцессор. Удивлен немало, что это для Вас новость sad.gif.


QUOTE (Petka @ Aug 28 2015, 22:13) *
Было бы забавно наблюдать что на единственно возможную конструкцию согласно правилам "MISRA C" транслятор при проверке будет выдавать предупреждение. smile3046.gif

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


QUOTE (Petka @ Aug 28 2015, 22:13) *
С точки зрения стандарта Си конструкция do-while-zero не является "Implementation-Defined Behavior", "Undefined behavior" или пр. Так что поводов "давать по рукам" программисту никаких нет.

Не давать, а ПРЕДУПРЕЖДАТЬ, что написанная программистом конструкция была бессмысленна и комилятор нее выкинул, но может программист не пожалевший времени на нажатие кнопок, все-же расситывал на какой-то другой эффект???
Petka
Цитата(zltigo @ Aug 28 2015, 22:22) *
Не смотря на то, что Вам так забавно, все так и происходит, если активизировать полный набор warnings. По умолчанию - не ругается.

Резюме: "вменяемый компилятор" по умолчанию не выдаёт предупреждение на вполне законную конструкцию. Плюсик к IAR Systems.
Цитата
Не давать, а ПРЕДУПРЕЖДАТЬ, что написанная программистом конструкция была бессмысленна и компилятор нее выкинул, но может программист не пожалевший времени на нажатие кнопок, все-же рассчитывал на какой-то другой эффект???

В качестве литературной гиперболы:

в конструкции:
Код
r = (a * b) + (c * d);

тоже есть "лишние конструкции", которые транслятор "выкинет". Например, скобки вообще "лишние". Да и пробелы совсем не нужны. Может программист "все-же рассчитывал этими скобками на какой-то другой эффект"?
Резюме: наличие широкого спектра предупреждений в трансляторах это хорошо. Но порою производители "инструментов" немного перегибают палку.

P.S. Модераторам: из топика имеет смысл обсуждение конструкции do-while-zero вынести в отдельную тему.
scifi
Цитата(zltigo @ Aug 28 2015, 22:22) *
Увы, это совершеная реальность - ПЕРЕД компиляцией сишный исходник проходит через препроцессор. Удивлен немало, что это для Вас новость sad.gif.

Вы будете смеяться, но перед вёрсткой текст книги проходит корректора, редактора и кого-то там ещё, наверное. И вы утверждаете, что редактор не может посмотреть на то, на что смотрит корректор? Пардон, но какую траву вы курите? Исходный текст злобные чекисты спрятали что ли? Я вас умоляю... twak.gif
zltigo
QUOTE (scifi @ Aug 29 2015, 00:14) *
Пардон, но какую траву вы курите? Исходный текст злобные чекисты спрятали что ли? Я вас умоляю... twak.gif

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

scifi
Цитата(zltigo @ Aug 29 2015, 00:32) *
От того, что Вы будете повторять дурь находящуюся в Вашей голове, Ваши фантазии о том, как должен работать препроцессор + компилятор ничего не изменят.

Мне более не интересно пытаться донести свою мысль до вас. Адью.
zltigo
QUOTE (Petka @ Aug 28 2015, 22:37) *
в конструкции:
CODE
r = (a * b) + (c * d);

тоже есть "лишние конструкции", которые транслятор "выкинет". Например, скобки вообще "лишние". Да и пробелы совсем не нужны. Может программист "все-же рассчитывал этими скобками на какой-то другой эффект"?

Вы, очевидно не поверите, но компилятор скобки не "выкинет", он выполнит НЕ РАСУЖДАЯ предписанные ими действия. С пробелами еще проще - их игнорирование описано стандартом, так-что компилятор де-юре не думает, что кто хотел сказать пробелами.
QUOTE
P.S. Модераторам: из топика имеет смысл обсуждение конструкции do-while-zero вынести в отдельную тему.

Уже была когда-то. Вторая никчему.
Petka
Цитата(zltigo @ Aug 29 2015, 00:43) *
Вы, очевидно не поверите,

Очевидно, тут не вопрос веры.
Цитата
но компилятор скобки не "выкинет", он выполнит НЕ РАССУЖДАЯ предписанные ими действия. С пробелами еще проще - их игнорирование описано стандартом, так-что компилятор де-юре не думает, что кто хотел сказать пробелами.

Сказали "А", говорите и "Б". Если "лишние" пробельные символы компилятор может удалять(игнорировать) без предупреждений, то и валидные конструкции "while(0)", "for(;;)", "#if 0", по той-же самой логике транслятор должен обрабатывать согласно стандарту "НЕ РАССУЖДАЯ".
Что бы не уводить обсуждение в сторону прошу подкрепить или опровергнуть Ваше заявление
Цитата
...Да и сам трюк, увы, грязноват, ибо while(константа) принципиально ошибочное выражение, хотя из-за его распространенности...

Откуда вы это взяли? Есть какой-то стандарт где это описано? Отраслевые инструкции? Исследования? В книжке какой-то прочитали? Бложик? Твиттер? Сплетни? С удовольствием ознакомлюсь с источником такой информации.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.