|
Детская ошибка |
|
|
|
May 2 2016, 06:22
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Недавно столкнулся с одной странностью (по крайней мере для меня). Хотелось бы понять. Есть фрагмент года (упрощенный до безобразия): CODE int16u temp1, temp2; for (int32u i = 0; i < 10; i++) { temp1 = 0x0001; temp2 = 0xFFFE; if (~temp1 != temp2) continue; temp2 = temp1; }
Так вот, в этом фрагменте условный оператор и код после него никогда не выполняется. В отладчике после выполнения операции "temp2 = 0xFFFE;" происходит сразу переход на начало цикла. Переменные объявлены как int16u (== unsigned short (16 бит беззнаковое)) При этом никаких предупреждений на этапе компиляции. Если переменные объявить как int32u (== unsigned long (32 бита беззнаковое)), то условный оператор выполняется, но естественно результат всегда true. И код работает как надо только в таком варианте: CODE int16u temp1, temp2; for (int32u i = 0; i < 10; i++) { temp1 = 0x0001; temp2 = 0xFFFE; temp1 = ~temp1; if (temp1 != temp2) continue; temp2 = temp1; }
В этом случае выполняются все операторы, входящие в тело цикла. IAR C/C++ Compiler for ARM 7.40.3.8902 (7.40.3.8902) Добавлю: Оптимизация отключена. Проект под микроконтроллер STM32F105VCT6
Сообщение отредактировал amiller - May 2 2016, 06:41
|
|
|
|
|
 |
Ответов
|
May 2 2016, 07:08
|
Частый гость
 
Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364

|
А если так: Код int16u temp1, temp2; for (int32u i = 0; i < 10; i++) { temp1 = 0x0001; temp2 = 0xFFFE; if ( (int16u)(~temp1) != temp2 ) continue; temp2 = temp1; }
|
|
|
|
|
May 2 2016, 07:16
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(AleksBak @ May 2 2016, 10:08)  А если так: Код int16u temp1, temp2; for (int32u i = 0; i < 10; i++) { temp1 = 0x0001; temp2 = 0xFFFE; if ( (int16u)(~temp1) != temp2 ) continue; temp2 = temp1; } Так как Вы предлагаете, тоже работает. Хотя в этом меня тоже смущает один момент. После выполнения оператора "~" не должна меняться размерность переменной. Но больше всего меня беспокоит результат компиляции первого моего примера. В ассемблерном коде вообще отсутствует условный оператор и всё, что после него. И при этом никаких предупреждений от компилятора. Как это можно рассматривать? Бага компилятора? Или есть более простое объяснение?
|
|
|
|
|
May 2 2016, 11:30
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(amiller @ May 2 2016, 10:16)  Но больше всего меня беспокоит результат компиляции первого моего примера. В ассемблерном коде вообще отсутствует условный оператор и всё, что после него. Вы будете смеяться, но компилятор вовсе не обязан на каждый чих в исходнике генерить код. Обычно на минимальном уровне оптимизации генерит, но тоже не всегда и не везде. Компилятор отвечает только за то, что сгенерированный код выдаст тот результат, который следует из исходника. Если исходник никакого результата не подразумевает, то компилятор может не генерировать ничего - и будет в своём праве. Цитата(amiller @ May 2 2016, 11:21)  1. Раньше во всех случаях, когда в коде был фрагмент, который никогда не выполняется, я получал от компилятора соответствующее предупреждение. В данном случае - нет. Это вам показалось. Если припомните, какое именно было предупреждение, то поймёте, что в данном случае оно не применимо. А если не припомните, то это просто испорченный телефон. Короче, показалось. Цитата(amiller @ May 2 2016, 11:21)  Но в этом случае компилятор не выбрасывает из кода условный оператор и всё что после него. Есть вероятность, что ответ на этот простой вопрос, как обычно, лежит в более сложных материях. Не надо там искать сложных материй. В одном случае выкинул бессмысленный код, в другом - нет. Подумаешь - бывает сплошь и рядом. Компилятор - это просто программа, а не какое-то высшее существо с высшим разумом.
|
|
|
|
|
May 2 2016, 11:35
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(scifi @ May 2 2016, 14:26)  Вы будете смеяться, но компилятор вовсе не обязан на каждый чих в исходнике генерить код. Обычно на минимальном уровне оптимизации генерит, но тоже не всегда и не везде. Компилятор отвечает только за то, что сгенерированный код выдаст тот результат, который следует из исходника. Если исходник никакого результата не подразумевает, то компилятор может не генерировать ничего - и будет в своём праве. В этом с Вами я согласен, но предупредить то надо. Например если поставить внутри функции безусловный return, генерится предупреждение. А в данном случае всё происходит молча. Ну и не совсем понятен алгоритм. В одном случае молча выбрасывает код, а в другом очень похожем случае всё же генерит код, который тем не менее также не выполняется. Например, если в том же примере заменить строку с условным оператором "if (true) continue;" то получаем предупреждение: Warning[Pe111]: statement is unreachable - что логично. А в моем примере это происходило "молча". Тем не менее всем спасибо! Ошибка локализована. И с утверждением, что компилятор "не обязан", я согласен. Остальное в общем то уже нюансы функционирования программы, которой также является и компилятор.
Сообщение отредактировал amiller - May 2 2016, 11:44
|
|
|
|
|
May 6 2016, 04:58
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(amiller @ May 2 2016, 14:35)  Ошибка локализована. И с утверждением, что компилятор "не обязан", я согласен. Остальное в общем то уже нюансы функционирования программы, которой также является и компилятор. 1. Странно, что локализована. Лично мне резануло глаз присваивание константы в цикле, при том что константа объявлена не volatile. Стало быть, весь цикл вообще теряет смысл. И никакие неявные приведения типов тут вообще ни причем. 2. Упрощения, это хорошо. Но приводить упрощенный Си-код вне функции, дело бесполезное. Хотя бы потому, что не понятно, переменные temp1 и temp2 локальные или глобальные. 3. Насчет обязан или не обязан компилер. Конечно не обязан, его дело компилировать. Зато статический анализатор кода сразу завопил бы, с негодованием. Благо в последних IAR встроен C-Stat. Настоятельно рекомендую натравить его на код. Гарантирую(с), он еще много "чудес" выявит в коде.
|
|
|
|
|
May 6 2016, 06:23
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(Tahoe @ May 6 2016, 07:58)  1. Странно, что локализована. Лично мне резануло глаз присваивание константы в цикле, при том что константа объявлена не volatile. Стало быть, весь цикл вообще теряет смысл. И никакие неявные приведения типов тут вообще ни причем. 2. Упрощения, это хорошо. Но приводить упрощенный Си-код вне функции, дело бесполезное. Хотя бы потому, что не понятно, переменные temp1 и temp2 локальные или глобальные. Если ошибка воспроизводится в такой простой конструкции, то зачем присылать страницы кода? Переменные temp1 и temp2 локальные, объявление на строчку выше. В исходном коде переменным присваиваются не константы, а результат, возвращаемый функцией. А после условного оператора ещё сотня строк в цикле. Меня лично смутило, что компилятор без предупреждений выбросил из программы большой фрагмент кода. Это было главное, на что я обратил внимание. Но раз общественность не забилась в праведном гневе, значит все считают это нормальным. А тогда вопрос и не стоит обсуждать. Тем более в коде был грешок с приведением типов, на который мне правильно указали.
|
|
|
|
|
May 6 2016, 08:32
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(amiller @ May 6 2016, 09:23)  Если ошибка воспроизводится в такой простой конструкции, то зачем присылать страницы кода? Еще раз. Нет никакой конструкции. Тот огрызок, что приведен, не позволяет нормально определить источник проблемы. Цитата(amiller @ May 6 2016, 09:23)  Переменные temp1 и temp2 локальные, объявление на строчку выше. В исходном коде переменным присваиваются не константы, а результат, возвращаемый функцией. "Не в преферанс, а в лотерею. Не миллион, а пять тыщ. И не выиграл, а проиграл." (с) Я только не понял, это вот "в исходном коде не константы", это просто поприкалываться захотелось или на полном серьезе? Цитата(amiller @ May 6 2016, 09:23)  Но раз общественность не забилась в праведном гневе, значит все считают это нормальным. А тогда вопрос и не стоит обсуждать.Тем более в коде был грешок с приведением типов, на который мне правильно указали. А, общественность... Все считают... Тогда другое дело. Это заявка на успех. Желаю удачи.
|
|
|
|
|
May 6 2016, 08:58
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(Tahoe @ May 6 2016, 11:32)  Еще раз. Нет никакой конструкции. Тот огрызок, что приведен, не позволяет нормально определить источник проблемы.
"Не в преферанс, а в лотерею. Не миллион, а пять тыщ. И не выиграл, а проиграл." (с)
Я только не понял, это вот "в исходном коде не константы", это просто поприкалываться захотелось или на полном серьезе?
А, общественность... Все считают... Тогда другое дело. Это заявка на успех. Желаю удачи. Извините, но я не понял к чему это всё, что Вы написали. Или Вы считаете, что если я скопирую сюда полный код функции, Вы точно укажете на источник проблемы? Или Вы считаете, что я школьник, и то, что я прислал к делу не имеет отношения, а ошибка в другом месте? Смею Вас заверить, что это не так. И проблема воспроизводится именно в том "огрызке", который я разместил, я специально проверял. Для этого больше ничего не нужно, достаточно этот фрагмент разместить в пустом main(). Ну разве что скорректировать названия типов. И в отзывах была информация, что это характерно не только для компилятора IAR. В gcc тоже проблема воспроизводится.
|
|
|
|
|
May 6 2016, 14:19
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(zltigo @ May 6 2016, 16:44)  Опять  . Да не проблема это компилятора, ЛЮБОЙ компилятор ОБЯЗАН поступить аналогично. Это АБСОЛЮТНО Ваша проблема связанная с незнаним языка. Я нигде не писал, что претендую на звание "гуру". Более того, на ошибках учусь с удовольствием, как на своих, так и на чужих. Но никто не дал на мой вопрос чёткий ответ. 1. Если переменные int16u, то компилятор код выбрасывает. У меня нет вопросов к самому факту этого события. У меня вопрос к тому, почему это происходит без предупреждения (молча). Я не считаю, что это нормальное поведение компилятора. 2. Однако если переменные int32u, то с точки зрения выполнения кода ничего не меняется. Но тем не менее в этом случае, код компилируется (не выбрасывается). Хотя результат также предопределен и известен заранее. Я уже вроде успокоился по этому поводу, но находятся всё новые люди, которые утверждают, что я не знаю язык, но не дают чёткого ответа, почему компилятор поступает именно так. Может Вы попробуете?
|
|
|
|
|
May 6 2016, 16:31
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(amiller @ May 6 2016, 17:19)  1. Если переменные int16u, то компилятор код выбрасывает. Последний раз, больше даже пытаться не стану. Если десять раз присвоить константу temp1=0x1, хоть что-то изменится, хоть на одном проходе из 10? Если не изменится, то бишь даже без всякой оптимизации, temp1 и temp2 _всегда_ будут иметь одно и то же значение. Результат if (~0x0001!= 0xFFFE) будет отличаться хоть на одном из проходов? И плевать какие там типы, все 10 раз будет одно и то же. А строчка temp2 = temp1; будет вообще игнорироваться. В итоге, имеем несколько строчек бессмысленного кода, который вырождается в пару присваиваний. И никакого цикла здесь нет. Другой вопрос, когда вместо констант будет присваиваться результат функции. В этом случае, может и дойдет до кривых типов. Но в приведенном куске, с константами, до этого дело даже не доходит.
|
|
|
|
|
May 7 2016, 02:52
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(Tahoe @ May 6 2016, 19:31)  Последний раз, больше даже пытаться не стану. Если десять раз присвоить константу temp1=0x1, хоть что-то изменится, хоть на одном проходе из 10? Если не изменится, то бишь даже без всякой оптимизации, temp1 и temp2 _всегда_ будут иметь одно и то же значение. Результат if (~0x0001!= 0xFFFE) будет отличаться хоть на одном из проходов? И плевать какие там типы, все 10 раз будет одно и то же. А строчка temp2 = temp1; будет вообще игнорироваться.
В итоге, имеем несколько строчек бессмысленного кода, который вырождается в пару присваиваний. И никакого цикла здесь нет. Другой вопрос, когда вместо констант будет присваиваться результат функции. В этом случае, может и дойдет до кривых типов. Но в приведенном куске, с константами, до этого дело даже не доходит. Уважаемый, не рассказывайте мне пожалуйста, о бессмысленных присвоениях и сравнениях констант. Вы невнимательно читали предыдущую переписку. Представленный фрагмент кода имеет только один смысл - продемонстрировать наличие проблемы в действиях компилятора. Вместо того, чтобы доказывать, что автор сообщения не умеет писать программы, постарались бы понять, что он хотел донести своим сообщением. Цитата(Сергей Борщ @ May 7 2016, 00:37)  Меняется. При приведении int16_t -> int32_t происходит расширение знака. Уточнение: мои типы int16u и int32u соответствуют uint16_t u uint32_t. Не уверен, что в этом случае можно говорить о расширении знака. Когда я говорил "ничего не меняется", я имел в виду, что условие в условном операторе по прежнему всегда true (не зависит от типа переменных), но в одном случае код компилируется, а в другом выбрасывается.
|
|
|
|
Сообщений в этой теме
amiller Детская ошибка May 2 2016, 06:22  Сергей Борщ QUOTE (amiller @ May 2 2016, 10:16) После... May 2 2016, 07:24   amiller Цитата(Сергей Борщ @ May 2 2016, 10:24) М... May 2 2016, 07:36    Сергей Борщ QUOTE (amiller @ May 2 2016, 10:36) Ну а ... May 2 2016, 08:09     amiller Цитата(Сергей Борщ @ May 2 2016, 11:09) Д... May 2 2016, 08:21    AleksBak Цитата(amiller @ May 2 2016, 15:35) В это... May 2 2016, 12:20    GetSmart Цитата(amiller @ May 2 2016, 15:35) В это... May 2 2016, 13:49     Baser Цитата(GetSmart @ May 2 2016, 16:49) Обна... May 2 2016, 16:18     ViKo Цитата(GetSmart @ May 2 2016, 16:49) Обна... May 2 2016, 16:19     Огурцов Цитата(GetSmart @ May 2 2016, 13:49) Хоро... May 2 2016, 16:36     jcxz Цитата(GetSmart @ May 2 2016, 19:49) Код{... May 3 2016, 15:33      GetSmart Цитата(jcxz @ May 3 2016, 19:33) И что в ... May 3 2016, 16:23       zltigo QUOTE (GetSmart @ May 3 2016, 19:23) Искр... May 3 2016, 19:47        GetSmart Цитата(zltigo @ May 3 2016, 23:47) Так чт... May 3 2016, 21:42       scifi Цитата(Tahoe @ May 6 2016, 11:32) Еще раз... May 6 2016, 08:45          scifi Цитата(amiller @ May 6 2016, 17:19) 1. Ес... May 6 2016, 15:29           Огурцов Цитата(scifi @ May 6 2016, 16:29) Предупр... May 7 2016, 16:57            scifi Цитата(Огурцов @ May 7 2016, 19:57) а не ... May 7 2016, 18:27            Tahoe Цитата(amiller @ May 7 2016, 05:52) Предс... May 7 2016, 05:14             amiller Цитата(Tahoe @ May 7 2016, 08:14) Предста... May 7 2016, 05:37              svss Цитата(amiller @ May 7 2016, 11:37) ...
5... May 7 2016, 09:24               zltigo QUOTE (svss @ May 7 2016, 12:24) не полаг... May 7 2016, 10:25              Tahoe Цитата(amiller @ May 7 2016, 08:37) А кро... May 7 2016, 13:47               amiller Цитата(Tahoe @ May 7 2016, 16:47) Так мож... May 7 2016, 14:04                Tahoe Цитата(amiller @ May 7 2016, 17:04) сразу... May 7 2016, 16:06                 amiller Цитата(Tahoe @ May 7 2016, 19:06) Не поня... May 7 2016, 17:33          Сергей Борщ QUOTE (amiller @ May 6 2016, 17:19) 2. Од... May 6 2016, 21:37      halfdoom Цитата(amiller @ May 6 2016, 09:23) Если ... May 9 2016, 06:43       amiller Цитата(halfdoom @ May 9 2016, 09:43) Где-... May 9 2016, 07:54     GetSmart Цитата(Tahoe @ May 6 2016, 08:58) 3. Насч... May 9 2016, 16:00      zltigo QUOTE (GetSmart @ May 9 2016, 19:00) Ещё ... May 9 2016, 16:11 aiwa Вообще-то да, это работа не компилятора, но редакт... May 4 2016, 11:59 aiwa Цитата(amiller @ May 7 2016, 08:37) 2. ..... May 7 2016, 07:59 aiwa Цитата(Огурцов @ May 7 2016, 19:57) а не ... May 7 2016, 20:41 Огурцов вы можете между собой договориться, есть в предпис... May 7 2016, 21:59 aiwa Цитата(Огурцов @ May 8 2016, 00:59) вы мо... May 7 2016, 22:31 zltigo QUOTE (aiwa @ May 8 2016, 01:31) Причем, ... May 8 2016, 03:44 Огурцов Цитата(aiwa @ May 7 2016, 22:31) А о чем ... May 8 2016, 06:05  jcxz Цитата(Огурцов @ May 8 2016, 12:05) о сво... May 8 2016, 06:18   Огурцов > Выбросил 2+3, заменил на 5. Сообщать?
скорее ... May 8 2016, 06:53    jcxz Цитата(Огурцов @ May 8 2016, 12:53) >В... May 8 2016, 13:30     Огурцов Цитата(jcxz @ May 8 2016, 13:30) Каким бо... May 8 2016, 14:53  ViKo Цитата(Огурцов @ May 8 2016, 09:05) о сво... May 8 2016, 06:18   jcxz Цитата(ViKo @ May 8 2016, 12:18) У Кейла ... May 8 2016, 06:32    ViKo Цитата(jcxz @ May 8 2016, 09:32) IAR всё ... May 8 2016, 07:18 ViKo Прочитав тему еще раз, понял, что топикстартер при... May 8 2016, 05:55 amiller Цитата(ViKo @ May 8 2016, 08:55) Прочитав... May 8 2016, 09:07 ViKo Keil
Example1
CODE; generated by Component: ARM Co... May 8 2016, 10:35 aiwa Цитата(Огурцов @ May 8 2016, 09:05) о сво... May 8 2016, 12:13 amiller Цитата(aiwa @ May 8 2016, 15:13) Так он в... May 8 2016, 12:24 aiwa Цитата(zltigo @ May 8 2016, 06:44) Маразм... May 8 2016, 12:29 ViKo И во что же должно продвинуться беззнаковое uint16... May 8 2016, 12:34 aiwa Цитата(amiller @ May 8 2016, 15:24) Вроде... May 8 2016, 12:54 aiwa Цитата(jcxz @ May 8 2016, 16:30) Хмммм...... May 8 2016, 14:27 ViKo Правильно, продвигается до знакового целого. Но по... May 8 2016, 14:37 jcxz Цитата(ViKo @ May 8 2016, 20:37) Правильн... May 8 2016, 16:41  Огурцов Цитата(jcxz @ May 8 2016, 17:41) Ещё раз ... May 8 2016, 18:19   jcxz Цитата(Огурцов @ May 9 2016, 00:19) ещё р... May 9 2016, 08:59 aiwa Цитата(ViKo @ May 8 2016, 17:37) Правильн... May 8 2016, 14:43 ViKo О! Может, топикстартер все же напутал с опреде... May 8 2016, 14:45 amiller Цитата(ViKo @ May 8 2016, 17:45) О! М... May 8 2016, 15:04 aiwa Цитата(ViKo @ May 8 2016, 17:45) О! М... May 8 2016, 15:24 ViKo Почему никто не комментирует листинги от Кейла? Вс... May 8 2016, 15:45 aiwa Цитата(ViKo @ May 8 2016, 18:40) Почему н... May 8 2016, 15:53 ViKo Кейл, он же Кайл, он же Keil (нем.), он же куплен ... May 8 2016, 15:57 scifi Цитата(ViKo @ May 8 2016, 18:57) Кейл, он... May 8 2016, 16:43 jcxz Цитата(ViKo @ May 8 2016, 21:57) Кейл, он... May 8 2016, 17:00 aiwa Цитата(ViKo @ May 8 2016, 18:57) Кейл, он... May 8 2016, 16:20 ViKo Дополню для ясности. У Cortex-M команды - THUMB2 -... May 8 2016, 18:11 ViKo Таки да, операция ~temp1 дает число 0xFFFFFFFE. Во... May 8 2016, 19:42 aiwa Цитата(ViKo @ May 8 2016, 22:42) Таки да,... May 8 2016, 22:52 aiwa Цитата(halfdoom @ May 9 2016, 09:43) Пере... May 9 2016, 11:10 zltigo QUOTE (aiwa @ May 9 2016, 14:10) В резуль... May 9 2016, 11:56  svss Цитата(zltigo @ May 9 2016, 17:56) Если ... May 10 2016, 05:13 halfdoom Цитата(aiwa @ May 9 2016, 14:10) В резуль... May 9 2016, 14:51 aiwa Цитата(zltigo @ May 9 2016, 14:56) Если ... May 9 2016, 12:41 scifi Цитата(aiwa @ May 9 2016, 15:41) Вы вопро... May 9 2016, 12:49  jcxz Цитата(scifi @ May 9 2016, 18:49) Было бы... May 9 2016, 16:51 zltigo QUOTE (aiwa @ May 9 2016, 15:41) Вы вопро... May 9 2016, 13:38  dxp QUOTE (zltigo @ May 9 2016, 19:38) Python... May 9 2016, 16:29   zltigo QUOTE (dxp @ May 9 2016, 19:29) Питон - в... May 9 2016, 16:57    dxp QUOTE (zltigo @ May 9 2016, 22:57) Ага. Б... May 10 2016, 06:57 aiwa Цитата(halfdoom @ May 9 2016, 17:51) Если... May 9 2016, 23:30 halfdoom Цитата(aiwa @ May 10 2016, 02:30) наводит... May 10 2016, 04:20  aiwa Цитата(halfdoom @ May 10 2016, 07:20) Ста... May 10 2016, 07:58   scifi Цитата(aiwa @ May 10 2016, 10:58) повторю... May 10 2016, 08:13   halfdoom Цитата(aiwa @ May 10 2016, 10:58) Все дов... May 10 2016, 08:49 aiwa Цитата(scifi @ May 10 2016, 11:13) Код, к... May 10 2016, 09:43
2 страниц
1 2 >
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|