Что делает ! в С?

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

Что делает ! в С?

Post by perasperaadastra »

Есть 1 байт, в котором нас интересует только последний бит. Я сделал while цикл, в котором использовал ~byte, думая, что это полностью аналогично !. Но оно не работало. То есть ! не переворачивает все биты, а делает что-то другое. Вопрос — что именно?
User avatar
Ion Tichy
Уже с Приветом
Posts: 13339
Joined: 07 Dec 2004 04:00
Location: Москва->CO

Re: Что делает ! в С?

Post by Ion Tichy »

perasperaadastra wrote: 18 May 2017 05:25 Есть 1 байт, в котором нас интересует только последний бит. Я сделал while цикл, в котором использовал ~byte, думая, что это полностью аналогично !. Но оно не работало. То есть ! не переворачивает все биты, а делает что-то другое. Вопрос — что именно?
Ну это как бы все знают:
Called Logical NOT Operator. It is used to reverse the logical state of its operand. If a condition is true, then Logical NOT operator will make it false.
Надеюсь не надо напоминать что 0 - фолс, а все что не 0 - тру? А уж как там ! внутри сделан - побитово, похренитово - это детали имплементации, спеки-стандарты такой ерундой не заморачиваются. "Не царское это дело в 3,14... ковыряться" (с) старый анек.
Как же это вы без гравицаппы пепелац выкатываете из гаража? Это непорядок...
User avatar
Ion Tichy
Уже с Приветом
Posts: 13339
Joined: 07 Dec 2004 04:00
Location: Москва->CO

Re: Что делает ! в С?

Post by Ion Tichy »

partner_ca wrote: 18 May 2017 05:49 Для инверсии битов можно использовать bitwise complement оператор ~
...и замаскировать все биты кроме последнего -если последний нужен- &1
Как же это вы без гравицаппы пепелац выкатываете из гаража? Это непорядок...
User avatar
Ion Tichy
Уже с Приветом
Posts: 13339
Joined: 07 Dec 2004 04:00
Location: Москва->CO

Re: Что делает ! в С?

Post by Ion Tichy »

partner_ca wrote: 18 May 2017 06:00
Ion Tichy wrote: 18 May 2017 05:54 ...и замаскировать все биты кроме последнего -если последний нужен- &1
Смотря который считать последним :-)
Для меня последний 0x80, а 0x01 - первый.
Еврей что ли или араб? Справа налево читаете?
Как же это вы без гравицаппы пепелац выкатываете из гаража? Это непорядок...
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Что делает ! в С?

Post by perasperaadastra »

Аааа! До меня наконец-то дошло! Когда я сделал

Code: Select all

while (~b) 
условие проваливалось из-за того, что флаг 0x01 (ИСТИНА) превращался в 0xFE (тоже ИСТИНА) вместо 0х00. Надо было маскировать последний бит, чтобы заработало:

Code: Select all

while ((~b)&0x01) 
while (!b) наверняка в это и компилируется на моем микроконтроллере.

Спасибо, пан Тихий за вправление мозгов! :fr:
User avatar
thinker
Уже с Приветом
Posts: 26871
Joined: 29 Aug 2000 09:01

Re: Что делает ! в С?

Post by thinker »

Что-то я не пойму если последний (младший) бит нужен, то почему нельзя сделать:
while(b&1)
All rights reserved, all wrongs revenged.
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Что делает ! в С?

Post by perasperaadastra »

К микроконтроллеру подключено устройство, которое рапортует байт. Когда байт "свежий", в нем выставляется флаг готовности. Поэтому нужна петля, в которой этот байт считывается до тех пор, пока флаг не становится TRUE

Code: Select all

do  {
     // считываем байт b
} while (!b);                        // выходим из петли если флаг 1
User avatar
thinker
Уже с Приветом
Posts: 26871
Joined: 29 Aug 2000 09:01

Re: Что делает ! в С?

Post by thinker »

while (!b) будет работать только если остальные биты в байте всегда нули.

Если же остальные биты могут быть не нулями то нужно while (!(b&1))

Так?
All rights reserved, all wrongs revenged.
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Что делает ! в С?

Post by perasperaadastra »

Вы абсолютно правы. Я несколько упростил детали. На самом деле в моем случае флаг находится в старшем бите, и вместо b стоит b>>7, что позволяет опускать маску при исползовании !
User avatar
thinker
Уже с Приветом
Posts: 26871
Joined: 29 Aug 2000 09:01

Re: Что делает ! в С?

Post by thinker »

ок, ясно.
Если без использования побитного шифта >>, тогда: while (!(b&0x80))
All rights reserved, all wrongs revenged.
User avatar
thinker
Уже с Приветом
Posts: 26871
Joined: 29 Aug 2000 09:01

Re: Что делает ! в С?

Post by thinker »

perasperaadastra wrote: 18 May 2017 17:21 К микроконтроллеру подключено устройство, которое рапортует байт. Когда байт "свежий", в нем выставляется флаг готовности. Поэтому нужна петля, в которой этот байт считывается до тех пор, пока флаг не становится TRUE

Code: Select all

do  {
     // считываем байт b
} while (!b);                        // выходим из петли если флаг 1
Кстати, тут b должна быть определена как volatile. А иначе компилятор может оптимизировать код так, что b будет прочитана только один раз, и ваша программа зависнет в бесконечном цикле.
All rights reserved, all wrongs revenged.
User avatar
AndreyT
Уже с Приветом
Posts: 3000
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Что делает ! в С?

Post by AndreyT »

perasperaadastra wrote: 18 May 2017 05:25 То есть ! не переворачивает все биты, а делает что-то другое. Вопрос — что именно?
По определению, в языке С выражение '!x' эквивалентно выражению 'x == 0'.
perasperaadastra wrote: 18 May 2017 06:16 while (!b) наверняка в это и компилируется на моем микроконтроллере.
Нет, конечно. Оно компилируется в 'while (b == 0)', как и должно.
Last edited by AndreyT on 19 May 2017 00:06, edited 1 time in total.
Best regards,
Андрей
User avatar
Ion Tichy
Уже с Приветом
Posts: 13339
Joined: 07 Dec 2004 04:00
Location: Москва->CO

Re: Что делает ! в С?

Post by Ion Tichy »

thinker wrote: 18 May 2017 21:57
perasperaadastra wrote: 18 May 2017 17:21...

Code: Select all

do  {
     // считываем байт b
} while (!b);                        // выходим из петли если флаг 1
Кстати, тут b должна быть определена как volatile. А иначе компилятор может оптимизировать код так, что b будет прочитана только один раз, и ваша программа зависнет в бесконечном цикле.
Вы бредите.
Как же это вы без гравицаппы пепелац выкатываете из гаража? Это непорядок...
User avatar
AndreyT
Уже с Приветом
Posts: 3000
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: Что делает ! в С?

Post by AndreyT »

Ion Tichy wrote: 18 May 2017 06:05
partner_ca wrote: 18 May 2017 06:00
Ion Tichy wrote: 18 May 2017 05:54 ...и замаскировать все биты кроме последнего -если последний нужен- &1
Смотря который считать последним :-)
Для меня последний 0x80, а 0x01 - первый.
Еврей что ли или араб? Справа налево читаете?
Биты нумеруются от младших к старшим, с тем только замечанием, что нумерация традиционно ведется с нуля. Поэтому "первым" натуральнее назвать младший бит, а "последним" - старший. То есть именно 0x01 - "первый", а 0x80 - "последний".

И да, нумерация разрядов в позиционной записи числа растет справа-налево. Для этого совсем не надо быть евреем или арабом.
Best regards,
Андрей
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Что делает ! в С?

Post by perasperaadastra »

AndreyT wrote: 18 May 2017 23:34
perasperaadastra wrote: 18 May 2017 05:25 То есть ! не переворачивает все биты, а делает что-то другое. Вопрос — что именно?
По определению, в языке С выражение '!x' эквивалентно выражению 'x == 0'.
perasperaadastra wrote: 18 May 2017 06:16 while (!b) наверняка в это и компилируется на моем микроконтроллере.
Нет, конечно. Оно компилируется в 'while (b == 0)', как и должно.
Спасибо за объяснение. :fr: Сейчас глянул в ассембли вывод, и оказывается на данном микроконтроллере это очень удобно реализуется через

Code: Select all

sbrs	(Skip if Bit in Register is Set)
rjmp	(relative jump)
User avatar
perasperaadastra
Уже с Приветом
Posts: 20128
Joined: 21 Feb 2009 22:55
Location: Лох Онтарио

Re: Что делает ! в С?

Post by perasperaadastra »

Ion Tichy wrote: 18 May 2017 23:36
thinker wrote: 18 May 2017 21:57
perasperaadastra wrote: 18 May 2017 17:21...

Code: Select all

do  {
     // считываем байт b
} while (!b);                        // выходим из петли если флаг 1
Кстати, тут b должна быть определена как volatile. А иначе компилятор может оптимизировать код так, что b будет прочитана только один раз, и ваша программа зависнет в бесконечном цикле.
Вы бредите.
Thinker имеет аргумент:
https://barrgroup.com/Embedded-Systems/ ... le-Keyword

Edit: или речь о другом?

Хотя в моем случае компилятор хранит эту переменную всегда только в регистре, поэтому нет опасности.
User avatar
thinker
Уже с Приветом
Posts: 26871
Joined: 29 Aug 2000 09:01

Re: Что делает ! в С?

Post by thinker »

perasperaadastra wrote: 19 May 2017 01:06Thinker имеет аргумент:
https://barrgroup.com/Embedded-Systems/ ... le-Keyword

Edit: или речь о другом?
Именно это.
All rights reserved, all wrongs revenged.
User avatar
Serguei666
Уже с Приветом
Posts: 18917
Joined: 11 Jul 2003 01:00

Re: Что делает ! в С?

Post by Serguei666 »

partner_ca wrote: 19 May 2017 01:17
perasperaadastra wrote: 19 May 2017 01:06 Edit: или речь о другом?

Хотя в моем случае компилятор хранит эту переменную всегда только в регистре, поэтому нет опасности.
volatatile - это в первую очередь про глобальные данныe, к которым возможен доступ из нескольких потоков.
В данном случае совсем не в тему.
Судя по тому, что написал perasperaadastra, у него эта b как раз пишется-читается из нескольких потоков.

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