реклама на сайте
подробности

 
 
> Проблема с условием, m = m+I|P == I ? m : 0;
ave!
сообщение Aug 20 2018, 08:18
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 20-05-11
Пользователь №: 65 166



Добрый день!

Я переношу чужую программу с AVR на STM32 (под HAL Keil).

m = m+I|P == I ? m : 0;

Эта строка выдает предупреждение: "| имеет более низкий приоритет, чем ==; == будет оцениваться сначала"
Когда пишу m = (m+I|P) == I ? m : 0; предупреждение исчезает, но я не знаю можно ли так писать, не нарушит ли эта запись условие.

Таких предупреждений много и есть более сложные выражения.

if (x+r-y|u&32|p > 2&(p-4|j-7 || b[G=x+3^r>>1&7]-k-6 || b[G^1]|b[G^2])) t += p<5; else F = y;

Warning: '&' within (внутри) '|'
Warning: & has lower precedence than >; > will be evaluated first
Warning: '&' within (внутри) '|'

Подскажите ссылку где можно поучится этим условиям в контексте моей проблемы.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
segment
сообщение Aug 20 2018, 08:55
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Воу. Если не секрет, то что это за проект такой? А так, Вам необходимо просто почитать о приоритетах операторов.
Go to the top of the page
 
+Quote Post
ave!
сообщение Aug 20 2018, 10:29
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 20-05-11
Пользователь №: 65 166



Цитата(segment @ Aug 20 2018, 11:55) *
Воу. Если не секрет, то что это за проект такой?

Это не секрет, это шахматная программа micro-Max.
Весь код помещается на одном листе А4, притом, что программа знает даже такое правило, как "взятие пешки на проходе".
Мне этот алгоритм очень понравился, я когда-то с друзьями в турнир играл, четырех обыграл, а эта програмка меня взувает (сделал шахматный калькулятор на ATmega48).
Тут верно заметили, что код писал математик.
Спасибо за советы.

Сообщение отредактировал ave! - Aug 20 2018, 10:42
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 20 2018, 11:31
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(ave! @ Aug 20 2018, 13:29) *
Тут верно заметили, что код писал математик.

Код писал извращенец человек, цель которого была совсем не оптимальность и не решение практической задачи, а цель - вычурность кода.
Ибо: вместо t += p<5 простой программист использует if, а более продвинутый заменит на что-то типа: t -= (int)(p - 5) >> 31;
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 22 2018, 12:33
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(jcxz @ Aug 20 2018, 15:31) *
Ибо: вместо t += p<5 простой программист использует if, а более продвинутый заменит на что-то типа: t -= (int)(p - 5) >> 31;


А еще результат выражения != 0 не обязательно есть 1. Поэтому тот, кто писал t += p<5, явно чудак biggrin.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 22 2018, 13:55
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Arlleex @ Aug 22 2018, 15:33) *
А еще результат выражения != 0 не обязательно есть 1.
Обязательно есть.
QUOTE (Arlleex @ Aug 22 2018, 15:33) *
Поэтому тот, кто писал t += p<5, явно чудак biggrin.gif
Тот, кто писал этот код, очень хорошо знал Стандарт языка. В отличие от вас.
QUOTE
6.5.8 Relational operators
6 Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.89)
The result has type int.
6.5.9 Equality operators
The == (equal to) and != (not equal to) operators are analogous to the relational
operators except for their lower precedence.90) Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result has type int.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 25 2018, 07:08
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(Сергей Борщ @ Aug 22 2018, 16:55) *
Обязательно есть.
Тот, кто писал этот код, очень хорошо знал Стандарт языка. В отличие от вас.

Вон оно как? Стандартов не читал, да, признаю.
Но вот будет ли так в дальнейшем - не совсем ясно, поэтому так писать лично я бы не стал. Ведь компиляторы все новее и новее, а оптимизация все хитрее. Никто не знает, во что это выльется в будущем.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 25 2018, 07:21
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Aug 25 2018, 10:08) *
Но вот будет ли так в дальнейшем - не совсем ясно, поэтому так писать лично я бы не стал. Ведь компиляторы все новее и новее, а оптимизация все хитрее. Никто не знает, во что это выльется в будущем.

Я тоже выше об этом писал. Понятно что сейчас это работает. Но такой подход и стиль считаю плохим.
char тоже раньше всегда был знаковым, а сейчас может быть и беззнаковым, в зависимости от установок компилятора. Всё потому, что в появились некоторые CPU, в которых чтение/запись беззнаковых char короче чем знаковых, и во многих случаях, когда знаковость не важна, лучше использовать такие операции чтения/записи.
Так и с этим - если CPU позволяет более эффективно работать с типами bool со значениями 0/-1, а не 0/1, то лучше так и делать, разрешив спец.опцией компилятора. Хотя конечно это гораздо менее часто встречающаяся потребность чем char, значит не очень важная.
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 25 2018, 07:39
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(jcxz @ Aug 25 2018, 10:21) *
Я тоже выше об этом писал. Понятно что сейчас это работает. Но такой подход и стиль считаю плохим.
char тоже раньше всегда был знаковым, а сейчас может быть и беззнаковым, в зависимости от установок компилятора.

Про CPU с различными подходами в копировании char не знал, спасибо. Интересно конечно, как это может так быть - ведь копируются 8 бит все равно...

А вот размышления вслух, можно сказать.
Допустим есть условие if(x != y) или просто выражение z = (x != y). Переменные целые. Я бы на месте компилятора сделал что-то наподобие z = x - y или z = x ^ y. И если z равно 0, то это значило, что x == y. А если не равно 0, то, соответственно, x != y. Вот типичный случай, когда не нужны были бы лишние телодвижения по установке значения 1 в переменную вместо прямого присваивания результата вычитания. Меньше инструкций ведь по факту. И таких примеров оптимизаций, ИМХО, можно как-то еще придумать. Опять же, просто исходя из логики рассуждаю laughing.gif

Сообщение отредактировал Arlleex - Aug 25 2018, 07:42
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 25 2018, 07:59
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Aug 25 2018, 10:39) *
Про CPU с различными подходами в копировании char не знал, спасибо. Интересно конечно, как это может так быть - ведь копируются 8 бит все равно...

Загляните как-нить в листинг Cortex-M3/4 кода и сравните команды LDRB и LDRSB например. Поймёте почему.
Для этого имхо и ввели дополнительный чекбокс в IAR "signed/unsigned char".
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 25 2018, 09:23
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(jcxz @ Aug 25 2018, 10:59) *
Загляните как-нить в листинг Cortex-M3/4 кода и сравните команды LDRB и LDRSB например. Поймёте почему.
Для этого имхо и ввели дополнительный чекбокс в IAR "signed/unsigned char".

Сходу не получилось заставить компилятор сгенерировать LDRSB...
Использую armcc в составе Keil. Оптимизация 0. Галка "Plain Char is Signed" сброшена.
Код
Код
volatile signed char a = 10;
volatile signed char b = 20;
volatile signed char c;

int main(void)
{
    c = a - b;
    
    while(1);
}

формирует следующий листинг
Код
0x080002E0 4805      LDR           r0,[pc,#20]
0x080002E2 7800      LDRB          r0,[r0,#0x00]; загрузили a
0x080002E4 4905      LDR           r1,[pc,#20]
0x080002E6 7809      LDRB          r1,[r1,#0x00]; загрузили b
0x080002E8 1A40      SUBS          r0,r0,r1     ; вычли
0x080002EA B240      SXTB          r0,r0        ; ИМХО, лишнее, т.к. SUBS работает 32-битными числами
0x080002EC 4904      LDR           r1,[pc,#16]
0x080002EE 7008      STRB          r0,[r1,#0x00]; загружаем результат в переменную c

В случае, если переменные объявить без спецификатора signed (то есть с unsigned) то листинг тот же самый, но без SXTB

С оптимизацией -O3 для signed/unsigned листинг одинаковый:
Код
0x0800028C 4803      LDR           r0,[pc,#12]
0x0800028E 7801      LDRB          r1,[r0,#0x00]
0x08000290 7842      LDRB          r2,[r0,#0x01]
0x08000292 1A89      SUBS          r1,r1,r2
0x08000294 7081      STRB          r1,[r0,#0x02]


Сообщение отредактировал Arlleex - Aug 25 2018, 09:33
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 25 2018, 09:59
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Aug 25 2018, 12:23) *
Сходу не получилось заставить компилятор сгенерировать LDRSB...
Использую armcc в составе Keil. Оптимизация 0. Галка "Plain Char is Signed" сброшена.

Всего лишь оптимизация умного компилятора rolleyes.gif
Вы сами подумайте: раз Вы результат обратно сокращаете до 8 бит, то зачем тогда старшие биты вычислять? А если их вычислять не нужно, то можно ограничиться командами LDRB как более "дешёвыми". laughing.gif
Тест Ваш построен некорректно. Для корректности теста сделайте int volatile c. Тогда, думаю, увидите LDRSB.
Ну и для теста можно одно из a или b сделать отрицательным.

Цитата(Arlleex @ Aug 25 2018, 12:23) *
0x080002EA B240 SXTB r0,r0 ; ИМХО, лишнее, т.к. SUBS работает 32-битными числами

Хоть это и лишнее, но это был намёк компилятора, что он заметил достаточность использования 8-бит для результата и поэтому не стал заморачиваться с правильным расширением входных аргументов. rolleyes.gif

PS: Код теста не совсем корректный, так как должен вызвать warning "undefined behavior".
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 25 2018, 10:24
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(jcxz @ Aug 25 2018, 12:59) *
Тест Ваш построен некорректно. Для корректности теста сделайте int volatile c. Тогда, думаю, увидите LDRSB.

Точно! И вправду LDRB заменились на LDRSB... Просто с расширением знака. Все четко по описанию команды загрузки с расширением знака rolleyes.gif
Единственное, что отмечу. Разницы в количестве тактов выполнения не заметно... То есть по факту выполняются они одинаково по времени, только лишь представление числа в памяти нужным образом расширяется или нет, вот и вся разница, вроде как.

Цитата(jcxz @ Aug 25 2018, 12:59) *
PS: Код теста не совсем корректный, так как должен вызвать warning "undefined behavior".

Из-за int перед main() и отсутствия возвращаемого результата? Тогда не неопределенное поведение, а что-то типа "недостижимый участок кода" и "отсутствие возвращаемого значения в функции, которая возвращает int"... Но Keil не паникует, кстати... laughing.gif
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 25 2018, 12:24
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Aug 25 2018, 13:24) *
Единственное, что отмечу. Разницы в количестве тактов выполнения не заметно... То есть по факту выполняются они одинаково по времени, только лишь представление числа в памяти нужным образом расширяется или нет, вот и вся разница, вроде как.

Конечно разницы в тактах нет при условии наличия команды в кеше/конвеере CPU. Но в реальном МК команду ещё нужно выбрать из памяти, а ширина шины к памяти программ не бесконечна, как и скорость последней.
Так что по времени выполнения - Вы не правы.

Цитата(Arlleex @ Aug 25 2018, 13:24) *
Из-за int перед main() и отсутствия возвращаемого результата?

Нет. Из-за того, что в одном выражении используются две volatile-переменные. Порядок чтения которых внутри выражения неопределён. А volatile подразумевает строгость в порядке доступа.

Цитата(Arlleex @ Aug 25 2018, 13:24) *
Но Keil не паникует, кстати... laughing.gif

А зря. IAR реагирует на подобные выражения: "undefined behavior".
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Aug 25 2018, 13:23
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(jcxz @ Aug 25 2018, 15:24) *
Конечно разницы в тактах нет при условии наличия команды в кеше/конвеере CPU. Но в реальном МК команду ещё нужно выбрать из памяти, а ширина шины к памяти программ не бесконечна, как и скорость последней.
Так что по времени выполнения - Вы не правы.

Открыл TRM на Cortex-M3. Вижу, что CPI на LDRB и на LDRSB одинаковы и составляют 2 такта. Одинакова и их синтаксическая запись. Существуют как 16-битные, так и 32-битные версии обеих команд. При всех прочих равных условиях время выполнения LDRB и LDRSB одинаково.
То, что команду нужно выбрать из памяти - это понятно. Но LDRB нужно выбрать точно так же, как и LDRSB в одном и том же коде. Ничем не отличается.
Другое дело, если мы говорим о том, что загружать значение как оно есть и лишь потом программно еще расширять знак. Там да, несколько команд нужно: тот же LDRB + расширение знака, если требуется.

Цитата(jcxz @ Aug 25 2018, 15:24) *
Нет. Из-за того, что в одном выражении используются две volatile-переменные. Порядок чтения которых внутри выражения неопределён. А volatile подразумевает строгость в порядке доступа.

Да, в упор не увидел очевидное... Жаль Keil не ругнулся никак даже при установке "All Warnings" в настройках компилятора crying.gif

Сообщение отредактировал Arlleex - Aug 25 2018, 13:24
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 25 2018, 13:49
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Arlleex @ Aug 25 2018, 16:23) *
Открыл TRM на Cortex-M3. Вижу, что CPI на LDRB и на LDRSB одинаковы и составляют 2 такта. Одинакова и их синтаксическая запись. Существуют как 16-битные, так и 32-битные версии обеих команд. При всех прочих равных условиях время выполнения LDRB и LDRSB одинаково.

А Вы когда-нибудь пробовали заглядывать в листинг? И сколько вы там видели LDRB разной длины и сколько LDRSB? laughing.gif
Формы-то может и есть, тут вопрос в количестве....
Попробуйте в .asm-файле ввести 2 такие команды и скомпилить:
Код
LDRB     R0, [R0, #0]
LDRSB     R0, [R0, #0]
А потом попробуйте поизменять регистры от R0 до R7 и посмотреть что получается.
А теперь загляните в листинги и увидите, что большинство обращений к памяти как раз подобные формы команд: косвенная с константным смещением.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ave!   Проблема с условием   Aug 20 2018, 08:18
- - aaarrr   Цитата(ave! @ Aug 20 2018, 11:18) Под...   Aug 20 2018, 08:45
|- - jcxz   Цитата(Arlleex @ Aug 22 2018, 15:33) А ещ...   Aug 22 2018, 13:02
|- - Arlleex   Цитата(jcxz @ Aug 25 2018, 16:49) А Вы ко...   Aug 25 2018, 14:15
- - ViKo   Дык, обфускация.   Aug 20 2018, 08:57
|- - aaarrr   Цитата(ViKo @ Aug 20 2018, 11:57) Дык, об...   Aug 20 2018, 09:05
- - segment   Да, да, она или дизассемблировано. Просто я однажд...   Aug 20 2018, 09:00
- - Сергей Борщ   QUOTE (ave! @ Aug 20 2018, 11:18) m =...   Aug 20 2018, 09:01
|- - Непомнящий Евгений   Цитата(Сергей Борщ @ Aug 20 2018, 12:01) ...   Aug 20 2018, 10:18
||- - Сергей Борщ   QUOTE (Непомнящий Евгений @ Aug 20 2018, 13...   Aug 20 2018, 11:25
||- - Непомнящий Евгений   Цитата(Сергей Борщ @ Aug 20 2018, 14:25) ...   Aug 20 2018, 12:35
|- - ave!   Цитата(Сергей Борщ @ Aug 20 2018, 12:01) ...   Aug 20 2018, 11:36
|- - jcxz   Цитата(ave! @ Aug 20 2018, 14:36) Исп...   Aug 20 2018, 11:47
|- - _pv   Цитата(jcxz @ Aug 20 2018, 18:47) Поэтому...   Aug 20 2018, 12:16
|- - ave!   Приоритет операций C++ - это я себе в тему на заме...   Aug 20 2018, 12:20
|- - jcxz   Цитата(ave! @ Aug 20 2018, 15:20) jcx...   Aug 20 2018, 12:23
|- - ave!   Цитата(jcxz @ Aug 20 2018, 15:23) Мне каж...   Aug 20 2018, 13:05
|- - jcxz   Цитата(ave! @ Aug 20 2018, 16:05) Сти...   Aug 20 2018, 13:24
|- - Сергей Борщ   QUOTE (jcxz @ Aug 20 2018, 16:24) Возможн...   Aug 20 2018, 13:28
|- - jcxz   Цитата(Сергей Борщ @ Aug 20 2018, 16:28) ...   Aug 20 2018, 13:30
- - jcxz   Цитата(ave! @ Aug 20 2018, 11:18) if ...   Aug 20 2018, 11:17
- - yes   ну дык (по описанию micro-Max) задача стояла миним...   Aug 20 2018, 14:28
|- - jcxz   Цитата(yes @ Aug 20 2018, 17:28) ну дык (...   Aug 20 2018, 16:12
- - ViKo   Поскольку было объяснение, что писалось на конкурс...   Aug 25 2018, 07:41
- - Obam   Во времена настали: раздел про AVR, а тут про приг...   Aug 25 2018, 19:46
|- - jcxz   Цитата(Obam @ Aug 25 2018, 22:46) Во врем...   Aug 25 2018, 19:58
- - Obam   Ну, на фоне 6502 и z80 вполне себе...   Aug 27 2018, 15:33


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 17:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01584 секунд с 7
ELECTRONIX ©2004-2016