Вопрос: IF (B00010000)

User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Вопрос: IF (B00010000)

Post by perasperaadastra »

Пытаюсь разобраться с побитовыми операциями в микропроцессорах AVR (среда ардуино). Застрял на том, как if интерпретирует результат & над двумя байтами. Для примера, такой кусочек кода:

Code: Select all

byte data = B10011101;
...
for (byte i=0; i<7; ++i) {
    if (data & (1<<i)) {
       // turn on the LED at location (i)
    } else {
      // turn off the LED at location (i)
 }
Пояснение такое:
The expression (1<<i) selects a given bit inside data that we want to access. Then using bitwise AND, data & (1<<i) tests the given bit. If that bit is set, a nonzero value results, causing the if to see it as being true. Otherwise, if the bit is zero, it is treated as false, so the else executes.
Допустим i = 4, и мы получили B00010000. Почему с точки зрения IF B00010000 то же самое, что true? В инструкции написано, что это просто такая условность (false = B00000000, а true - любой другой бит). Это такая особенность библиотек arduino или общепринятое поведение? Как обычно определяются константы true/false в других языках?
DropAndDrag
Уже с Приветом
Posts: 6018
Joined: 11 Mar 2011 05:36

Re: Вопрос: IF (B00010000)

Post by DropAndDrag »

не врубаюсь в их и ваше пояснение, но гореть будет при 0, 2, 3, 4, 7
операция & - в данном случае работает по битам. к примеру,
B10011101 & B00000010 = B00000000, то есть false.
B10011101 & B00010000 = B00010000, то есть больше нуля и поэтому true.
B10011101 & B00010001 = B00010001
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Вопрос: IF (B00010000)

Post by perasperaadastra »

DropAndDrag wrote:не врубаюсь в их и ваше пояснение, но гореть будет при 0, 2, 3, 4, 7
операция & - в данном случае работает по битам. к примеру,
B10011101 & B00000010 = B00000000, то есть false.
B10011101 & B00010000 = B00010000, то есть больше нуля и поэтому true.
B10011101 & B00010001 = B00010001
Мой вопрос конкретно по
то есть больше нуля и поэтому true.
Это стандарт С или вообще во всех языках так? Как насчет машинного кода — как определяется TRUE и FALSE на низком уровне?
User avatar
Medium-rare
Уже с Приветом
Posts: 9195
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: Вопрос: IF (B00010000)

Post by Medium-rare »

Это такая особенность библиотек arduino или общепринятое поведение?
Вопрос по старому доброму C. Ответ.
... and even then it's rare that you'll be going there...
DropAndDrag
Уже с Приветом
Posts: 6018
Joined: 11 Mar 2011 05:36

Re: Вопрос: IF (B00010000)

Post by DropAndDrag »

да в С так. возможно не больше нуля, а не равно 0.
у вас возможно не С, так как byte в С не было (что сейчас - не знаю), хотя может быть вы определили это слово.
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Вопрос: IF (B00010000)

Post by perasperaadastra »

Спасибо за ответы!

Arduino это просто библиотеки под С, поэтому и необычный вид кода. Ок, с С понятно: все, что не ноль, есть TRUE. А как дела, например в JAVA? Ну и самое главное, как true/false определяются на низком уровне — что это там: бит, байт или что-то иное? Как IF (B00010000) будет выглядеть в машинном коде?
DropAndDrag
Уже с Приветом
Posts: 6018
Joined: 11 Mar 2011 05:36

Re: Вопрос: IF (B00010000)

Post by DropAndDrag »

а может взять книжку и почитать ;-)
для обычных языков я избегаю делать, как в вашем примере, а всегда не ленюсь дописать == true или > 0. поэтому безразлична разница в вариантах по умолчанию.
с ассемблером по другому, если мне не изменяет память. там есть команды сравнения (==, >=, >, <, <=, !=) одного операнда или регистра с 0, так и между 2 операндами/регистрами. Операнды/регистры могут быть байты, слова, а теперь наверное и 32битные, и 64 битные длинные слова. Также операнды могут отличаться способом адресации ... так что команд там выше крыши.
когда-то писал, а щас уже ничего не помню. не помню куда результат записывается )))
User avatar
adb
Уже с Приветом
Posts: 9275
Joined: 14 Dec 2001 10:01
Location: Российская Федерация

Re: Вопрос: IF (B00010000)

Post by adb »

perasperaadastra wrote:Спасибо за ответы!

Arduino это просто библиотеки под С, поэтому и необычный вид кода. Ок, с С понятно: все, что не ноль, есть TRUE. А как дела, например в JAVA? Ну и самое главное, как true/false определяются на низком уровне — что это там: бит, байт или что-то иное? Как IF (B00010000) будет выглядеть в машинном коде?
Нету true/false на низком уровне. Есть арифмитические сравнения. Число больше нуля, число больше числа и т.п..
Миру мир
User avatar
Dmitry67
Уже с Приветом
Posts: 28294
Joined: 29 Aug 2000 09:01
Location: SPB --> Gloucester, MA, US --> SPB --> Paris

Re: Вопрос: IF (B00010000)

Post by Dmitry67 »

именно
все это идет от операций процессора, который тупо проверяет на ноль
эх, молодежь...
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Вопрос: IF (B00010000)

Post by perasperaadastra »

Теперь немножко проясняется ситуация. Спасибо всем за объяснения! :fr:

Извините, что спрашиваю такие азы — для меня это относительно новое хобби, никак не связанное с моей профессией. Книжку надо почитать, конечно. Сейчас нашел пару книг по микропрам AVR, гляну — авось интересное чтение.
User avatar
AndreyT
Уже с Приветом
Posts: 3000
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Вопрос: IF (B00010000)

Post by AndreyT »

perasperaadastra wrote:Это стандарт С или вообще во всех языках так? Как насчет машинного кода — как определяется TRUE и FALSE на низком уровне?
В языке С нет никакого TRUE и FALSE. В языке С изначально не было и булевского типа.

Операторы, порождающие семантически "булевский" результат, на самом деле порождают результат типа 'int' со значениями 0 и 1.

Конструкции (statements) и операторы, ожидающие "булевского" операнда, на самом деле ожидают операнд любого типа, синтаксически сравнимого с 0. Неравенство нулю рассматривается как "истина", равенство нулю - как "ложь".

(Булевский тип в С появился только в С99 под именем '_Bool', но и его значения - это все те же целочисленные 0 и 1.)

Таким образом в С конструкция 'if (a)' всегда эквивалентна 'if (a != 0)'.
Last edited by AndreyT on 21 May 2016 02:18, edited 1 time in total.
Best regards,
Андрей
User avatar
ALV00
Уже с Приветом
Posts: 1494
Joined: 08 Mar 2002 10:01
Location: NJ

Re: Вопрос: IF (B00010000)

Post by ALV00 »

perasperaadastra wrote:Теперь немножко проясняется ситуация. Спасибо всем за объяснения! :fr:

Извините, что спрашиваю такие азы — для меня это относительно новое хобби, никак не связанное с моей профессией. Книжку надо почитать, конечно. Сейчас нашел пару книг по микропрам AVR, гляну — авось интересное чтение.
Там можно дизассемблировать объектный файл
avr-objdump -d file.elf
Elf создается IDE где-то в temp директориях
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Вопрос: IF (B00010000)

Post by perasperaadastra »

AndreyT wrote:
perasperaadastra wrote:Это стандарт С или вообще во всех языках так? Как насчет машинного кода — как определяется TRUE и FALSE на низком уровне?
В языке С нет никакого TRUE и FALSE. В языке С изначально не было и булевского типа.

Операторы, порождающие семантически "булевский" результат, на самом деле порождают результат типа 'int' со значениями 0 и 1.

Конструкции (statements) и операторы, ожидающие "булевского" операнда, на самом деле ожидают операнд любого типа, синтаксически сравнимого с 0. Неравенство нулю рассматривается как "истина", равенство нулю - как "ложь".

(Булевский тип в С появился только в С99 под именем '_Bool', но и его значения - это все те же целочисленные 0 и 1.)

Таким образом в С конструкция 'if (a)' всегда эквивалентна 'if (a != 0)'.
Спасибо за подробное объяснение! :fr:
Int для булева типа это расточительство в микроконтроллере, где каждый байт на счету. Выходит, выгоднее булевы переменные объявлять типом Char, или, если если логических перемен много, загонять их в индивидуальные биты общей переменной.
User avatar
AndreyT
Уже с Приветом
Posts: 3000
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Вопрос: IF (B00010000)

Post by AndreyT »

perasperaadastra wrote:Int для булева типа это расточительство в микроконтроллере, где каждый байт на счету.
Никакого расточительства тут на самом деле нет. Результат [почти] любого оператора в языке С - это rvalue, т.е. значение, которое существует лишь концептуально, как некий промежуточный результат в последовательности вычислений. Способ хранения этого промежуточного значения (если оно вообще где-то хранится) пользователю не виден и не доступен, поэтому компилятор может хранить его каким угодно образом - хоть в одном байте, хоть в одном бите. Ни один разумный компилятор не будет буквально интерпретировать спецификацию и явно выделять целый 'int' для хранения каждого преомежуточного rvalue с гарантированными значениями 0 и 1. Зачем? Более того, в большинстве случаев, как уже говорилось выше, результаты таких операций зачастую вообще становятся лишь флагами состояния процессора после выполнения операции сравнения. А далее, на основе этих флагов выполняется (или не выполняется) условный переход.

Так что ни к какой "расточительности" это не приводит. То, что "логический" результат операции в С имеет тип 'int', имеет своей целью лишь гарантировать семантику арифметических операций над такими результатами, если вы вдруг захотите заняться такой арифметикой. Например, язык гарантирует, что выражение '(a > b) - (a < b)' порождает результат -1, 0 или +1 без возникновения каких-то арифметических переполнений.
perasperaadastra wrote:Выходит, выгоднее булевы переменные объявлять типом Char, или, если если логических перемен много, загонять их в индивидуальные биты общей переменной.
... А физическое хранение "булевских" значений в памяти - это уже совсем другой вопрос. Это ваш выбор. Язык вам говорит, что результат операции - это либо 0, либо 1, что значит, что вы можете выбрать соврешенно любой целочисленый тип для хранения этого значения. Язык вас никак здесь не огранчивает. Можете и в индивидуальные биты загонять.
Best regards,
Андрей

Return to “Вопросы и новости IT”