Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Детская ошибка
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Страницы: 1, 2, 3, 4
Огурцов
> Выбросил 2+3, заменил на 5. Сообщать?
скорее нет, чем да

>Выбросил (y+2) во втором выражении, заменив на x*3. Сообщать?
скорее да, чем нет

>если DEF_X != 1, то будет выкинута операция if и выражение1. Сообщать?
определённо да, ибо иначе использовался ifdef


Цитата(jcxz @ May 8 2016, 06:32) *
если среди них трудно найти полезные

пишите так, чтобы не было неполезных
ViKo
Цитата(jcxz @ May 8 2016, 09:32) *
IAR всё может. Только какая польза от такого кол-ва предупреждений, если среди них трудно найти полезные и всё равно их приходится отключать?

Отчего же сразу отключать? "Сначала - так, потом - вот так" (с) Сначала компилируем, чтобы без ошибок, потом блох начинаем вычесывать. Потом чисто будет, можно и не проверять.
Да, Назначения (Target) можно разные создать, чтоб одной кнопкой мышки... У меня два обычно, Debug и Release. Можно добавить Checked, типа...
amiller
Цитата(ViKo @ May 8 2016, 08:55) *
Прочитав тему еще раз, понял, что топикстартер привел гипотетический пример, который и не пробовал компилировать. И народ кинулся обсуждать, приводить доводы за и против для того, что в реальности невозможно.
Предлагаю выдать проверенный компилятором исходный текст.

Ну что же Вы право...
Если усомнились, что же сами не проверили?
example1.c - переменные 16 битные, код не формируется (example1.lst).
example2.c - переменные 32 битные, код формируется (example2.lst).
Оптимизация - None. Понятно, что в данном конкретном случае, когда присваиваются константы, компилятор на высоком уровне оптимизации может выбросить вообще весь код.
Но без оптимизации на этом фрагменте всё воспроизводится так, как я описал.
Нажмите для просмотра прикрепленного файла



ViKo
Keil
Example1
CODE
; generated by Component: ARM Compiler 5.06 update 1 (build 61) Tool: ArmCC [4d35ad]
; commandline ArmCC [--c99 --list --split_sections --debug -c --asm --interleave -o.\objects\example1.o --asm_dir=.\Listings\ --list_dir=.\Listings\ --depend=.\objects\example1.d --cpu=Cortex-M3 --apcs=interwork -O0 --diag_suppress=9931 -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE" -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE\Device\STM32F103VC" -IC:\Design\Keil\ARM\PACK\ARM\CMSIS\4.5.0\CMSIS\Include -IC:\Design\Keil\ARM\PACK\Keil\STM32F1xx_DFP\2.1.0\Device\Include -D__UVISION_VERSION=518 -D_RTE_ -DSTM32F10X_HD --omf_browse=.\objects\example1.crf Source\example1.c]
THUMB

AREA ||i.main||, CODE, READONLY, ALIGN=1

main PROC
;;;1 int main ()
000000 2000 MOVS r0,#0
;;;2 {
;;;3 unsigned short temp1, temp2;
;;;4 for (unsigned int i = 0; i < 10; i++)
000002 e009 B |L1.24|
|L1.4|
;;;5 {
;;;6 temp1 = 0x0001;
000004 2101 MOVS r1,#1
;;;7 temp2 = 0xFFFE;
000006 f64f72fe MOV r2,#0xfffe
;;;8 if (~temp1 != temp2) continue;
00000a 43cb MVNS r3,r1
00000c 4293 CMP r3,r2
00000e d000 BEQ |L1.18|
000010 e001 B |L1.22|
|L1.18|
;;;9 temp2 = temp1;
000012 460a MOV r2,r1
000014 bf00 NOP ;8
|L1.22|
000016 1c40 ADDS r0,r0,#1 ;4
|L1.24|
000018 280a CMP r0,#0xa ;4
00001a d3f3 BCC |L1.4|
;;;10 }
;;;11 }
00001c 2000 MOVS r0,#0
00001e 4770 BX lr
ENDP


__ARM_use_no_argv EQU 0


Example2
CODE
; generated by Component: ARM Compiler 5.06 update 1 (build 61) Tool: ArmCC [4d35ad]
; commandline ArmCC [--c99 --list --split_sections --debug -c --asm --interleave -o.\objects\example2.o --asm_dir=.\Listings\ --list_dir=.\Listings\ --depend=.\objects\example2.d --cpu=Cortex-M3 --apcs=interwork -O0 --diag_suppress=9931 -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE" -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE\Device\STM32F103VC" -IC:\Design\Keil\ARM\PACK\ARM\CMSIS\4.5.0\CMSIS\Include -IC:\Design\Keil\ARM\PACK\Keil\STM32F1xx_DFP\2.1.0\Device\Include -D__UVISION_VERSION=518 -D_RTE_ -DSTM32F10X_HD --omf_browse=.\objects\example2.crf Source\example2.c]
THUMB

AREA ||i.main||, CODE, READONLY, ALIGN=1

main PROC
;;;1 int main ()
000000 2000 MOVS r0,#0
;;;2 {
;;;3 unsigned int temp1, temp2;
;;;4 for (unsigned int i = 0; i < 10; i++)
000002 e009 B |L1.24|
|L1.4|
;;;5 {
;;;6 temp1 = 0x0001;
000004 2101 MOVS r1,#1
;;;7 temp2 = 0xFFFE;
000006 f64f72fe MOV r2,#0xfffe
;;;8 if (~temp1 != temp2) continue;
00000a 43cb MVNS r3,r1
00000c 4293 CMP r3,r2
00000e d000 BEQ |L1.18|
000010 e001 B |L1.22|
|L1.18|
;;;9 temp2 = temp1;
000012 460a MOV r2,r1
000014 bf00 NOP ;8
|L1.22|
000016 1c40 ADDS r0,r0,#1 ;4
|L1.24|
000018 280a CMP r0,#0xa ;4
00001a d3f3 BCC |L1.4|
;;;10 }
;;;11 }
00001c 2000 MOVS r0,#0
00001e 4770 BX lr
ENDP


__ARM_use_no_argv EQU 0



Keil победил! biggrin.gif
aiwa
Цитата(Огурцов @ May 8 2016, 09:05) *
о своих действиях - выбросил код, обнаружил невыполняемый или недостижимый код - сообщи

Так он выбросил код, проанализировав if(0). Случай исключительно вырожденный, так что и сообщать ему не о чем.

Грубо говоря, процесс "ошибки" заложен внутри выражения (~temp1 != temp2)
в результате перехода lvalue temp1 16 -> rvalue temp1 32.

amiller
Цитата(aiwa @ May 8 2016, 15:13) *
Так он выбросил код, проанализировав if(0). Случай исключительно вырожденный, так что и сообщать ему не о чем.

Грубо говоря, процесс "ошибки" заложен внутри выражения (~temp1 != temp2)
в результате перехода lvalue temp1 16 -> rvalue temp1 32.

А давайте утрируем ситуацию:
CODE

main ()
{
unsigned int temp1, temp2;
for (unsigned int i = 0; i < 10; i++)
{
temp1 = 0x0001;
temp2 = 0xFFFE;
if (1) continue;
temp2 = temp1;
}
}

Вроде как здесь всё ещё более определено. Так ведь нет. В этом случае видим предупреждение:
Warning[Pe111]: statement is unreachable H:\work\test\example2.c 9
Где логика то?

aiwa
Цитата(zltigo @ May 8 2016, 06:44) *
Маразм процветает sad.gif. Причем тут "старые", или "новые" - в огороде бузина а в Киеве дядька sad.gif. Компиляция такого "примера" зависит от разрядности int целевой платформы и ни от чего более.

Спасибо, конечно, за оценку но речь, как бы не о механизме действия компилятора, - их вполне полно и лаконично уже описал Сергей Борщ.

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

ViKo
И во что же должно продвинуться беззнаковое uint16_t 0xfffe? Разве не в 0x0000fffe, независимо, знаковое или без 32 битовое?
И продвигаться надо когда? Когда результат логического сравнения используется? Сказано же, сравнивать 16-битовые беззнаковые.
По-моему, IAR накосячил.
aiwa
Цитата(amiller @ May 8 2016, 15:24) *
Вроде как здесь всё ещё более определено. Так ведь нет. В этом случае видим предупреждение:
Warning[Pe111]: statement is unreachable H:\work\test\example2.c 9
Где логика то?

Точно не знаю, могу лишь предположить, что в этом случае все уже предопределено
на уровне синтаксического разбора, поэтому компилятор выдает предупреждение.
Но если Вы поменяете на
Код
int16u tst = 1;
if(tst) continue;

то сообщение уже может отсутствовать.



Цитата(ViKo @ May 8 2016, 15:34) *
И во что же должно продвинуться беззнаковое uint16_t 0xfffe? Разве не в 0x0000fffe, независимо, знаковое или без 32 битовое?
И продвигаться надо когда? Когда результат логического сравнения используется? Сказано же, сравнивать 16-битовые беззнаковые.
По-моему, IAR накосячил.

Продвинутое uint16_t 0xfffe равно 0xfffffffe и оно является строго знаковым, независимо от знаковости или беззнаковости исходной переменной.
Процесс продвижки начинается с упоминания имени переменной в выражении, а именно temp1 в выражении означает значение rvalue (signed int 32), полученное
из lvalue переменной temp1 с помощью правил расширения.

jcxz
Цитата(Огурцов @ May 8 2016, 12:53) *
>Выбросил (y+2) во втором выражении, заменив на x*3. Сообщать?
скорее да, чем нет

Зачем??? Это обычная оптимизация никак не влияющая на выполнение кода. Таких оптимизаций в исходниках может быть тысячи случаев. Какая от них польза?
Один только вред из-за того, что среди такого мусора пропадут полезные сообщения.

Цитата(Огурцов @ May 8 2016, 12:53) *
>если DEF_X != 1, то будет выкинута операция if и выражение1. Сообщать?
определённо да, ибо иначе использовался ifdef

wacko.gif Каким боком тут ifdef??? Его значение всегда будет true.
А смысл этого кода например в том, что есть некий общий модуль исходного кода на 2 разных устройства.
В одном устройстве например установлено два чипа SPI-FLASH в другом - один. И данный define задаёт кол-во чипов.
Это если Вы не поняли.

Цитата(ViKo @ May 8 2016, 13:18) *
Отчего же сразу отключать? "Сначала - так, потом - вот так" (с) Сначала компилируем, чтобы без ошибок, потом блох начинаем вычесывать. Потом чисто будет, можно и не проверять.

Причём тут ошибки? Ошибок нет. Преобразование типа - это стандартная операция. Тем более - оптимизация и лишний код удаляемый оптимизацией.
Таких событий будут тысячи мест в коде.

Цитата(aiwa @ May 8 2016, 18:54) *
Продвинутое uint16_t 0xfffe равно 0xfffffffe и оно является строго знаковым, независимо от знаковости или беззнаковости исходной переменной.

Хмммм.... А что такое "продвинутое uint16_t"? Я отстал от жизни и в си ввели новые "продвинутые" типы?
И как именно из беззнакового 0xFFFE получается 0xFFFFFFFE?
aiwa
Цитата(jcxz @ May 8 2016, 16:30) *
Хмммм.... А что такое "продвинутое uint16_t"? Я отстал от жизни и в си ввели новые "продвинутые" типы?
И как именно из беззнакового 0xFFFE получается 0xFFFFFFFE?

Продвинутый - это буквальный перевод термина "promotions", наверное неудачный.
Правила "integral promotions" предписывают расширение до типа способного полностью представить исходное значение
в порядке int, unsigned int, long int, unsigned long int, и т.д.
Первый тип для 32-го компилятора - знаковый int может полностью представить весь диапазон значений uint16_t, поэтому
и происходит расширение uint16_t - > signed int (32).
ViKo
Правильно, продвигается до знакового целого. Но почему 65534 должно "превратиться в -1?
jcxz, об чем вы, о каких ошибках? Я где хочу,там пишу с ошибками, а компилятор их ловит. Где хочу читаю все ремарки.
aiwa
Цитата(ViKo @ May 8 2016, 17:37) *
Правильно, продвигается до знакового целого. Но почему 65534 должно "превратиться в -1?
jcxz, об чем вы, о каких ошибках? Я где хочу,там пишу с ошибками, а компилятор их ловит. Где хочу читаю все ремарки.

Ах, точно, Вы правы - у меня опечятка: в результате расширения получается знаковый 0x0000FFFE.
ViKo
О! Может, топикстартер все же напутал с определением своего типа беззнакового?
Огурцов
Цитата(jcxz @ May 8 2016, 13:30) *
Каким боком тут ifdef???

таким, что если бы я хотел написать нечто осмысленное, то использовал ifdef
а так как написан if, то вероятно тут косяк, о коем компилятор обязан сообщить
amiller
Цитата(ViKo @ May 8 2016, 17:45) *
О! Может, топикстартер все же напутал с определением своего типа беззнакового?

Когда я разместил примеры в файлах - там уже стандартные названия сишных типов, как раз чтобы не было путаницы.

aiwa
Цитата(ViKo @ May 8 2016, 17:45) *
О! Может, топикстартер все же напутал с определением своего типа беззнакового?

Знаковость тут присутствует лишь в силу упоминания правил "integral promotions".
В случае, если бы temp1 и temp2 были знаковыми, результат был совершенно тем же.

Грубо говоря, написанный код if (~temp1 != temp2) компилятор видит как if(~rvalue32(temp1)!=rvalue32(temp2))

~rvalue32(temp1) совершенно другое значение нежели ~temp1.
ViKo
Почему никто не комментирует листинги от Кейла? Все пытаются оправдать ИАР.

Цитата(amiller @ May 8 2016, 18:04) *
Когда я разместил примеры в файлах - там уже стандартные названия сишных типов, как раз чтобы не было путаницы.

И Кейл их скомпилировал, как надо.
aiwa
Цитата(ViKo @ May 8 2016, 18:40) *
Почему никто не комментирует листинги от Кейла? Все пытаются оправдать ИАР.

Кто такой Билл наслышан, Кейла не знаю?
ИАР действует в соответствии со стандартом, а этот результат заложен там.
И это не оправдание, а всего лишь констатация печального факта.


Цитата(ViKo @ May 8 2016, 18:45) *
И Кейл их скомпилировал, как надо.


С АРМами пока не работал, но если не ошибаюсь, то Вы компилировали для 16-ти битного режима.
А в нем же uint16_t совпадает с unsigned int, поэтому происходит расширение до rvalue16(temp1).
При этом ~rvalue16(temp1) полностью совпадает с ~temp1.
ViKo
Кейл, он же Кайл, он же Keil (нем.), он же куплен ARM (АРМ), поскольку, как выясняется, компилирует без косяков.
aiwa, ошибаетесь.
aiwa
Цитата(ViKo @ May 8 2016, 18:57) *
Кейл, он же Кайл, он же Keil (нем.), он же куплен ARM (АРМ), поскольку, как выясняется, компилирует без косяков.
aiwa, ошибаетесь.

Я ничего не утверждаю - увидел в Ваших листингах "THUMB" вот и высказал предположение.
Если он компилирует верно и для 32-разрядного режима, то только можно этому порадоваться.
Есть надежда, что и в стандарт внесут соответствующие изменения.
jcxz
Цитата(ViKo @ May 8 2016, 20:37) *
Правильно, продвигается до знакового целого. Но почему 65534 должно "превратиться в -1?
jcxz, об чем вы, о каких ошибках? Я где хочу,там пишу с ошибками, а компилятор их ловит. Где хочу читаю все ремарки.

Я не знаю о каких ошибках писали Вы. Не узнаёте свои слова? Уже начали отмечать или ещё не закончили? biggrin.gif

Цитата(Огурцов @ May 8 2016, 20:53) *
таким, что если бы я хотел написать нечто осмысленное, то использовал ifdef
а так как написан if, то вероятно тут косяк, о коем компилятор обязан сообщить

Ещё раз прочитайте по буквам: причём там ifdef???
Для справки: ifdef - используется для проверки определено ли данное имя или нет.
В моём примере константа всегда определена. Но может принимать разные значения (1, 2, ...).
И то, что там написан if - вполне нормально, а никакой не косяк. Поэтому компилятор правильно и молчит.
В си аргумент оператора if - выражение, которое может состоять из переменных и констант.
На этапе выполнения значение этого выражения вычисляется. На этапе компиляции может осуществляться оптимизация этого выражения.
Варнингов на приведённые мною примеры не должно быть никаких. Что и подтверждает IAR.

PS: Тут уже все отмечают что-ль??? santa2.gif

Цитата(ViKo @ May 8 2016, 21:45) *
Почему никто не комментирует листинги от Кейла? Все пытаются оправдать ИАР.

Может потому что его никто не пользует? sm.gif
И зачем оправдывать IAR? Он не выдал варнинг? Так и правильно сделал!
scifi
Цитата(ViKo @ May 8 2016, 18:57) *
Кейл, он же Кайл, он же Keil (нем.), он же куплен ARM (АРМ), поскольку, как выясняется, компилирует без косяков.

Да? Именно поэтому сразу после покупки АРМ заменил кейловский убогий компилятор своим (он же RealView)? biggrin.gif
Кейл неплохо делает всё остальное (среда, отладчик, поддержка огромного зоопарка МК), но в компиляторах они точно не чемпионы.
jcxz
Цитата(ViKo @ May 8 2016, 21:57) *
Кейл, он же Кайл, он же Keil (нем.), он же куплен ARM (АРМ), поскольку, как выясняется, компилирует без косяков.
aiwa, ошибаетесь.

Посмотрел Ваш результат компиляции Кейл. Результат этот не делает чести Кейлу - теперь точно не променяю IAR на него! laughing.gif
IAR на этапе компиляции правильно оптимизировал выражение выкинув ненужный код.
Кейл-же оставил бессмысленный код. Значение выражения всегда будет "истина".
Так что: MVNS и CMP - лишние, а BEQ надо заменить на безусловный B.

Цитата(aiwa @ May 8 2016, 21:53) *
С АРМами пока не работал, но если не ошибаюсь, то Вы компилировали для 16-ти битного режима.
А в нем же uint16_t совпадает с unsigned int, поэтому происходит расширение до rvalue16(temp1).
При этом ~rvalue16(temp1) полностью совпадает с ~temp1.

Бред.
В ARM разрядность операций и регистров не зависит от режима - хоть Thumb хоть ARM - всё равно 32 бита.
Режимы ARM и Thumb - определяют только способ кодирования инструкций и их количество.
К тому-же, указанный ТС-ом МК, имеет ядро Cortex-M, которое знает только набор инструкций Thumb2.
Учите матчасть!
ViKo
Дополню для ясности. У Cortex-M команды - THUMB2 - смесь 16-битовых и 32пбитовых команд. А регистры, естественно, 32-битовые.
jcxz, я не отмечаю... Но подлечиться не помешает. Перестаю понимать людей.
Что касается Кейла, то он сделал то, что ему задали. Задам ему оптимизацию, посмотрим, что выдаст... Кто чемпион... чем сердце успокоится...
scifi, значит, RealView чемпион. Мне одинаково хорошо.

Задал -o3. Но, поскольку temp не volatile, Кейл выкинул всё. В обоих случаях снова все одинаково.
CODE
; generated by Component: ARM Compiler 5.06 update 1 (build 61) Tool: ArmCC [4d35ad]
; commandline ArmCC [--c99 --list --split_sections --debug -c --asm --interleave -o.\objects\example1.o --asm_dir=.\Listings\ --list_dir=.\Listings\ --depend=.\objects\example1.d --cpu=Cortex-M3 --apcs=interwork -O3 --diag_suppress=9931 -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE" -I"D:\ViKo\Works\Keil works\(Keil) Example\RTE\Device\STM32F103VC" -IC:\Design\Keil\ARM\PACK\ARM\CMSIS\4.5.0\CMSIS\Include -IC:\Design\Keil\ARM\PACK\Keil\STM32F1xx_DFP\2.1.0\Device\Include -D__UVISION_VERSION=518 -D_RTE_ -DSTM32F10X_HD --omf_browse=.\objects\example1.crf Source\example1.c]
THUMB

AREA ||i.main||, CODE, READONLY, ALIGN=1

main PROC
;;;311 /* end of stdint.h */
;;;3 int main ()
000000 2000 MOVS r0,#0
|L1.2|
;;;4 {
;;;5 uint16_t temp1, temp2;
;;;6 for (unsigned int i = 0; i < 10; i++)
000002 1c40 ADDS r0,r0,#1
000004 280a CMP r0,#0xa
;;;7 {
;;;8 temp1 = 0x0001;
;;;9 temp2 = 0xFFFE;
;;;10 if (~temp1 != temp2) continue;
000006 d3fc BCC |L1.2|
;;;11 temp2 = temp1;
;;;12 }
;;;13 }
000008 2000 MOVS r0,#0
00000a 4770 BX lr
ENDP


__ARM_use_no_argv EQU 0
Огурцов
Цитата(jcxz @ May 8 2016, 17:41) *
Ещё раз прочитайте по буквам: причём там ifdef???
Для справки: ifdef - используется для проверки определено ли данное имя или нет.
В моём примере константа всегда определена. Но может принимать разные значения (1, 2, ...).

ещё раз прочитайте ответ - вы обязаны записать это выражение правильно, иначе получайте предупреждение
кто должен разбираться, что там у вас там такое эти 1, 2..., или вы сможете вспомнить через полгода, что оно означало ?
ViKo
Таки да, операция ~temp1 дает число 0xFFFFFFFE. Вот если результат инверсии сохранить в uint16_t, тогда урежется до 0xFFFE.
Я тут внес сумятицу в дискуссию...
Отладчик Кейловский (чемпион!) рулит.
aiwa
Цитата(ViKo @ May 8 2016, 22:42) *
Таки да, операция ~temp1 дает число 0xFFFFFFFE. Вот если результат инверсии сохранить в uint16_t, тогда урежется до 0xFFFE.


Вот именно. Для правильной генерации кода, наверное, предлагается напомнить компилятору о правильной размерности таким кодом:
if( (int16u)(~temp1) != temp2)

Который явно не способствует читабельности.

Абыдно, что у С++ масло маслянное.
halfdoom
Цитата(amiller @ May 6 2016, 09:23) *
Если ошибка воспроизводится в такой простой конструкции, то зачем присылать страницы кода?
Переменные temp1 и temp2 локальные, объявление на строчку выше. В исходном коде переменным присваиваются не константы, а результат, возвращаемый функцией. А после условного оператора ещё сотня строк в цикле.


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

Перепишем ваш пример в более корректную форму:
Код
unsigned short test1(unsigned short temp1, unsigned short temp2)
{
    for (unsigned i = 0; i < 10; i++) {
        if (~temp1 != temp2) continue;
        temp2 = temp1;
    }
    return temp2;
}

и посмотрим на труд комиплятора (gcc -O2):
Код
    movl    %esi, %eax
    ret

Все просто превосходно - не правда ли? Цикл заменен единственной инструкцией, а все потому, что сам код при любых значениях входных переменных будет всегда возвращать значение переменной temp2. Компилятор увидел это, и выкинул абсолютно ненужный цикл.

Что-же касается молчаливого выбрасывания "мертвого" кода, то это есть следствие многопроходности современных компиляторов и весьма сложных структур внутреннего представления. Кроме того, конструкции вида
Код
constexpr bool WTF = true;
...
if (WTF) {
  save_the_world();
} else {
  destroy_the_moon();
}


широко используются при условной компиляции без использования препроцессора.
amiller
Цитата(halfdoom @ May 9 2016, 09:43) *
Где-то вы не договариваете. Тот код, что вы привели с локальными переменными, с позиции современных
компиляторов является "мертвым" кодом и может быть выкинут безо всяких предупреждений даже на низших
уровнях оптимизации.

Поверьте, ничего я не "не договариваю". В топике я разместил код в таком виде, в каком проблема (на мой взгляд))
воспроизводилась, и с которой я столкнулся. Я считал что этого достаточно, так как легко можно проверить.
Затем, в сообщении 53 я привел законченные примеры кода и результат компиляции IAR.
Вопрос, как и тема раздела в целом, касается исключительно IAR. Причём на уровне оптимизации - None.
Причём я по прежнему считаю, что логика формирования предупреждений у IAR страдает.
1. Переменные 16 битные - код выбрасывается без предупреждений. Вроде мы обосновали, что это логично.
2. Переменные 32 битные - код присутствует, хотя он в этом случае он не менее бессмысленный.
Хотя здесь может быть такой аргумент: Две 32 битные переменные имеют право сравниваться, а компилятор заранее
не обязан предсказывать результат.
3. В случае "if (true) continue;" предупреждение есть, хотя результат ещё более определен, чем в первом случае.
Для меня лично (по результатам обсуждения) логично бы выглядело наличие предупреждения и в первом пункте.
Но видимо это уже связано с многопроходностью компилятора (код выбрасывается на уровне, когда предупреждения
уже не формируются).
Наверное нельзя это оценивать однозначно как хорошо или как плохо. Просто надо иметь в виду, что такая ситуация
возможна и больше обращать внимание на такие неявные на первый взгляд особенности языка и действий компилятора.
jcxz
Цитата(Огурцов @ May 9 2016, 00:19) *
ещё раз прочитайте ответ - вы обязаны записать это выражение правильно, иначе получайте предупреждение
кто должен разбираться, что там у вас там такое эти 1, 2..., или вы сможете вспомнить через полгода, что оно означало ?

Что именно неправильно в моей записи и почему?
aiwa
Цитата(halfdoom @ May 9 2016, 09:43) *
Перепишем ваш пример в более корректную форму:

Код
// глобальные переменные
#define A ((int16u)0x01)  

int16u temp1 =   A;
int16u temp2 = ~A;
............................
void func(void)
{
  if (~temp1 != temp2)
  {
    printf(" не выполняется закон двойного отрицания ~~A = A");
  }
}


В результате работы компилятора будет выполнен выводящий сообщение блок.
zltigo
QUOTE (aiwa @ May 9 2016, 14:10) *
В результате работы компилятора будет выполнен выводящий сообщение блок.

Если "программист" не знает языка и НЕ ХОЧЕТ читать сообщения компилятора ПОДАВИВ ИХ, то да.

aiwa
Цитата(zltigo @ May 9 2016, 14:56) *
Если "программист" не знает языка и НЕ ХОЧЕТ читать сообщения компилятора ПОДАВИВ ИХ, то да.

Вы вопрос качества языка постоянно сводите к вопросу качества программиста.
scifi
Цитата(aiwa @ May 9 2016, 15:41) *
Вы вопрос качества языка постоянно сводите к вопросу качества программиста.

Язык такой, какой он есть. Де факто стандарт для программирования микроконтроллеров. Мы все крепки задним умом. Было бы неплохо, конечно, обобщить передовой опыт, родить супер-пупер язык для МК, который в 100500 раз более лучше, чем Си, и отправить его на машине времени туда, куда надо. Но что-то мне подсказывает, что троечникам это не поможет. Учебник всё равно надо читать.
zltigo
QUOTE (aiwa @ May 9 2016, 15:41) *
Вы вопрос качества языка постоянно сводите к вопросу качества программиста.

Есть язык, он описан. Как любой ЖИВОЙ язык он имеет опоеделенные правила и умолчания. Их надо знать. Если кто не знает языка и более того, плюет на сообщения, которые генерят компиляторы написанные знающими язык людьми, то это есть проблема "качества порограммиста" и только его.



QUOTE (scifi @ May 9 2016, 15:49) *
родить супер-пупер язык..

Спасибо, не надо. Уже рожали. Когда пытабтся рожать язык ради языка, а не дела, то получабтся ублюдки типа Ada, Python и иже с ними.
halfdoom
Цитата(aiwa @ May 9 2016, 14:10) *
В результате работы компилятора будет выполнен выводящий сообщение блок.


И что вас здесь смущает? Левый операнд оператора сравнения будет расширен до размера int, а затем инвертирован, что на 32-х битной архитектуре приведет к установке битов старшего слова в 1. Правый операнд в силу беззнакового типа будет дополнен нулями. Очевидно, что 0xffffxxxx != 0x0000xxxx. Если сделать первый операнд знаковым, то результат может показаться странным, т.к. числа до 0х8000 будут давать другой результат. В любом случае, это полностью документированное в стандарте поведение - никаких неожиданностей здесь нет.
GetSmart
Цитата(Tahoe @ May 6 2016, 08:58) *
3. Насчет обязан или не обязан компилер. Конечно не обязан, его дело компилировать. Зато статический анализатор кода сразу завопил бы, с негодованием. Благо в последних IAR встроен C-Stat. Настоятельно рекомендую натравить его на код. Гарантирую(с), он еще много "чудес" выявит в коде. wink.gif

Если в законе что-то не написано прямым текстом, то работает принцип аналогии.

Ещё со времён динозавров, компиляторы паскаля, си и многих других языков выдавали сообщение/варнинг при сравнении беззнаковой переменной со знаковой константой или или переменной с константой вне диапазона этой переменной. В примере топикстартера есть аналогичные признаки: сравнение двух выражений, которые заведомо вне диапазона друг друга. Программер имеет право ожидать, что ОБНАРУЖИВ подобную ситуацию, компилятор укажет на неё аналогично константе.

Если компилятор не слишком оптимизирующий, то он действительно может не выдавать сообщение, т.к. во время компиляции эту ситуацию не видит. Компилятор, опознавший always-result в выражении с переменными всё-таки должен (ака вектор эволюции) выдавать сообщение, по аналогии с другими предупреждениями. И профсоюз по защите прав программистов должен лоббировать эти правила )))

Молчание ИАРа тянет на недоработку. Если в публичных и непубличных нормативах не было явно указано на данную ситуацию.
zltigo
QUOTE (GetSmart @ May 9 2016, 19:00) *
Ещё со времён динозавров, компиляторы паскаля, си и многих других языков выдавали сообщение/варнинг при сравнении беззнаковой переменной со знаковой константой или или переменной с константой вне диапазона этой переменной.

Они и сейчас так делают.
QUOTE
Молчание ИАРа тянет на недоработку. Если в публичных и непубличных нормативах не было явно указано на данную ситуацию.

Никакого МОЛЧАНИЯ у IAR, как и других нет, если не не подавлять сообщения. IAR в отношении сообщалок о возможном непонимании, пожалуй даже говорливее всех других:

temp2 = ~A;
[Pa091]: operator operates on value promoted to int (with possibly unexpected result)


if( ~temp1 != temp2)
[Pa091]: operator operates on value promoted to int (with possibly unexpected result)
[Pe068]: integer conversion resulted in a change of sign

Так что может хватит здесь пургу нести?





dxp
QUOTE (zltigo @ May 9 2016, 19:38) *
Python и иже с ними.

Питон-то чем не угодил?

При всём уважении, по питону вы ни с какой стороны не правы! Питон - великолепный язык, очень простой, но при этом необычайно мощный, гибкий. И создавался он не ради языка, а как язык для обучения программированию, но оказался очень эффективным и для решения практических задач.
jcxz
Цитата(scifi @ May 9 2016, 18:49) *
Было бы неплохо, конечно, обобщить передовой опыт, родить супер-пупер язык для МК, который в 100500 раз более лучше, чем Си, и отправить его на машине времени туда, куда надо. Но что-то мне подсказывает, что троечникам это не поможет. Учебник всё равно надо читать.

Неумехи просто станут делать другие ошибки. И опять будут во всём винить компилятор. А больше ничего не изменится.
zltigo
QUOTE (dxp @ May 9 2016, 19:29) *
Питон - великолепный язык, очень простой, но при этом необычайно мощный, гибкий.

Ага. Беды начинаются, когда "обучившиеся программированию" начинают на нем программировать sad.gif.
QUOTE
И создавался он не ради языка, а как язык для обучения программированию

Вот то, что он создавался для обучения программированию - вот это и есть родимое пятно всех "языков ради языка". Ни Си ни Си++, ни тот же Perl не создавались для обучения, они создавались для РАБОТЫ.
QUOTE
, но оказался очень эффективным и для решения практических задач.

"Мама мыла раму..." © sad.gif. В реальности, все хуже - не далее, как месяц назад очередная утилитка тупо отказалась запускаться вываливаясь с характерными питоновскими воплями sad.gif. Утилитка о NXP/Jennic просто командная строка, но зачем то размером 250K и DLL-ок на полмега. За что?
aiwa
Цитата(halfdoom @ May 9 2016, 17:51) *
Если сделать первый операнд знаковым, то результат может показаться странным, т.к. числа до 0х8000 будут давать другой результат.

Вот как раз если первый операнд сделать знаковым, то в случае операции ~ красота картинки сохранится:
temp2 = 0xFFFE расширится его до 0xFFFFFFFE, а последующая операция ~temp2 обнулит лишние старшие навязанные два байта.

Поэтому в начальном примере код if(~(signed int16)temp2 !=temp1) continue; даст ожидаемый результат.

Цитата(halfdoom @ May 9 2016, 17:51) *
И что вас здесь смущает?


Согласно великому классику "В компиляторе все должно быть прекрасно...".
В нашем конкретном случае с логическими побитовыми операциями вынужденность добавления явных преобразований похожих на
Код
if(~(signed int16)temp2 !=temp1) continue;

либо

if( (unsigned int16)(~temp2) !=temp1) continue;

наводит на мысль, что некоторые моменты в стандарте шиворот-навыворот.
halfdoom
Цитата(aiwa @ May 10 2016, 02:30) *
наводит на мысль, что некоторые моменты в стандарте шиворот-навыворот.


Стандарт не обязан быть логичным для всех, потому что это стандарт. Однако если вспомнить, что все операции над переменными типа char и short производятся только после приведения к типу int, то многое становится понятным. Почему к int? Потому что существовали и, видимо, существуют архитектуры в которых арифметические операции возможны только для операндов с размером машинного слова, которое и представлено типом int. Иными словами, правила преобразований в С архитектурно зависимы, и в спорных случаях следует использовать явное приведение типов.

Кроме того, попробуйте разобраться, как должны работать следующие операторы:
Код
unsigned short a, b;

if (~(a + b) & ~0xf) {...}

short a, b;

if (~(a + b) & ~0xf) {...}
svss
Цитата(zltigo @ May 9 2016, 17:56) *
Если "программист" не знает языка и НЕ ХОЧЕТ читать сообщения компилятора ПОДАВИВ ИХ, то да.

Бывает хуже. Например IAR выдаёт предупреждение "unreachable code", а Keil то же место тихо-спокойно пропускает.
(прямо относится к исходному мессаджу)

О сколько нам открытий трудных..
dxp
QUOTE (zltigo @ May 9 2016, 22:57) *
Ага. Беды начинаются, когда "обучившиеся программированию" начинают на нем программировать sad.gif.

Беспредметное, безосновательное утверждение.

QUOTE (zltigo @ May 9 2016, 22:57) *
Вот то, что он создавался для обучения программированию - вот это и есть родимое пятно всех "языков ради языка". Ни Си ни Си++, ни тот же Perl не создавались для обучения, они создавались для РАБОТЫ.

Языком для обучения он позиционировался в 1990 году, с тех пор практически сразу стал языком для решения практических задач. Его ни в коем случае нельзя сравнивать с C/C++ - совершенно разные возможности и ниши, но если сравнивать с перлом, то сравнение будет не в пользу последнего.

QUOTE (zltigo @ May 9 2016, 22:57) *
"Мама мыла раму..." © sad.gif. В реальности, все хуже - не далее, как месяц назад очередная утилитка тупо отказалась запускаться вываливаясь с характерными питоновскими воплями sad.gif. Утилитка о NXP/Jennic просто командная строка, но зачем то размером 250K и DLL-ок на полмега. За что?

Понятия не имею, в чём вы. Программа на питоне - это текстовый скрипт. Для исполнения она требует исполняемой среды. Про какие dll речь, мне не ведомо.

Если наводите критику, так делайте это предметно. Конкретно что кривого в питоне, какие косяки в его дизайне. Про Аду не спрашиваю, про неё сам знаю. И Ада - действительно искусственно созданный ЯП по ТЗ МО США. Но питон - нет, у него совершенно другая история и свой путь развития. И питону уже не надо доказывать своё право на существование - он давно это доказал делом. Когда я познакомился с питоном лет 10 назад, так забыл как страшный сон эти sed'ы и awk, и с тех пор все утилиты для себя пишу на питоне, ни разу не пришлось разочароваться. И у всех, кого знаю, кто познакомился с питоном, чем плотнее знакомство, тем выше оценка. Подозреваю, что вы с ним реально почти не знакомы, но пришлось столкнуться с парой образчиков говнокода, отсюда и мнение о языке. Тут можно напомнить, что на сях легко наговнкодить так, что питонам и не снилось. Но это не характеризует сам язык.
aiwa
Цитата(halfdoom @ May 10 2016, 07:20) *
Стандарт не обязан быть логичным для всех, потому что это стандарт.

Полностью согласен, но мне кажется он должен при возможности следовать канонам формальной логики.
Компилятору желательно еще быть и удобным: повторюсь с примером, когда знаковый тип 'char' компилятор всегда
трактует как 'unsigned char' по желанию пользователя.


Цитата(halfdoom @ May 10 2016, 07:20) *
Потому что существовали и, видимо, существуют архитектуры в которых арифметические операции возможны только для операндов с размером машинного слова, которое и представлено типом int. Иными словами, правила преобразований в С архитектурно зависимы, и в спорных случаях следует использовать явное приведение типов.

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

Цитата(halfdoom @ May 10 2016, 07:20) *
Кроме того, попробуйте разобраться, как должны работать следующие операторы:
Код
unsigned short a, b;

if (~(a + b) & ~0xf) {...}

short a, b;

if (~(a + b) & ~0xf) {...}


Все довольно просто: результат (unsigned short+unsigned short) не будет 'unsigned short' потому что операция суммирования выходит за пределы разрядной сетки 'unsigned short' и результат будет зависеть от архитектуры в согласии с правилами целочисленного расширения.
scifi
Цитата(aiwa @ May 10 2016, 10:58) *
повторюсь с примером, когда знаковый тип 'char' компилятор всегда трактует как 'unsigned char' по желанию пользователя.

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

Цитата(aiwa @ May 10 2016, 10:58) *
Если компилятор способен сгенерировать ожидаемый код при явном приведении типов ((uint16_t)~temp1), то неплохо бы иметь такую возможность по умолчанию, не мозоля пальцы на явное преобразование и впоследствии глаза при чтении текста.

Код, который для вас кажется ожидаемым, для кого-то другого легко может быть неожиданным. Логика стандарта при приведении типов абсолютно понятна: она заточена под традиционную арифметику с числами. Операции над битами - это нечто иное. Ну что ж, привыкайте. Почитайте стандарт, и тогда компилятор не будет выдавать "неожиданный код".
halfdoom
Цитата(aiwa @ May 10 2016, 10:58) *
Все довольно просто: результат (unsigned short+unsigned short) не будет 'unsigned short' потому что операция суммирования выходит за пределы разрядной сетки 'unsigned short' и результат будет зависеть от архитектуры в согласии с правилами целочисленного расширения.

Пример немного не об этом, но уж раз вы завели речь о разрядной сетке - при использовании uint8_t вместо short все равно будет расширение типа до int, хотя результат помещается в short.

Цитата(dxp @ May 10 2016, 09:57) *
Языком для обучения он позиционировался в 1990 году, с тех пор практически сразу стал языком для решения практических задач. Его ни в коем случае нельзя сравнивать с C/C++ - совершенно разные возможности и ниши, но если сравнивать с перлом, то сравнение будет не в пользу последнего.

Это, конечно, жуткий оффтопик, но здесь с вами согласен - сравнивать питон следует только с перлом или авк.

Цитата(dxp @ May 10 2016, 09:57) *
Если наводите критику, так делайте это предметно. Конкретно что кривого в питоне, какие косяки в его дизайне.


Претензий к нему не много, но они вшиты намертво и меняться не будут:

отвратительный дизайн ООП модели (числа и строки не являются объектами, никуда не годный синтаксис доступа к родительским классам - сравните с C++);
очень медленные треды (из-за кривого дизайна интерпретатора), решается вывертами типа мультипроцессинга;
global/nonlocal - это вообще без комментариев;
де-факто существуют две несовместимые версии языка: python2/python3, а так-же наблюдается антагонизм сторонников как первого, так и второго;
однострочные лямбды - ограничение, видимо, произрастает из семантической значимости величины отступа.

Мы попытались перенести проект написанный на C++ и убедились, что овчинка совершенно не стоит выделки. А вот для скриптов, тест-модулей и прочих несложных программ питон подходит просто идеально, но здесь с ним в конкуренцию вступает Ruby.
aiwa
Цитата(scifi @ May 10 2016, 11:13) *
Код, который для вас кажется ожидаемым, для кого-то другого легко может быть неожиданным.

Я не имею ввиду себя или еще кого-то конкретно. Ожидаемый - с точки зрения формальной логики: если b=~а то-> ~b == а.

Цитата(halfdoom @ May 10 2016, 11:49) *
Пример немного не об этом, но уж раз вы завели речь о разрядной сетке - при использовании uint8_t вместо short все равно будет расширение типа до int, хотя результат помещается в short.

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

В принципе, все сводится к случаю, когда источником операнда для ~ является lvalue-значение.

Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.