|
Детская ошибка |
|
|
|
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 9 2016, 06:43
|

Профессионал
    
Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072

|
Цитата(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 Детская ошибка 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      Tahoe Цитата(amiller @ May 6 2016, 09:23) Если ... May 6 2016, 08:32       scifi Цитата(Tahoe @ May 6 2016, 11:32) Еще раз... May 6 2016, 08:45       amiller Цитата(Tahoe @ May 6 2016, 11:32) Еще раз... May 6 2016, 08:58        zltigo QUOTE (amiller @ May 6 2016, 11:58) И в о... May 6 2016, 13:44         amiller Цитата(zltigo @ May 6 2016, 16:44) Опять ... May 6 2016, 14:19          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 6 2016, 17:19) 1. Ес... May 6 2016, 16:31           amiller Цитата(Tahoe @ May 6 2016, 19:31) Последн... May 7 2016, 02:52            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       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 >
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|