Что "!!" в C?

Я столкнулся со следующим фрагментом:

pt->aa[!!(ts->flags & MASK)] = -val;
  1. Что означает !! (двойные восклицательные знаки/восклицательные знаки/два не оператора) в c?
  2. Не (!! NULL) == NULL ?
37
@Jan, этот вопрос помечен как c , и связанный с ним вопрос помечен как c . если теги неверны, они должны быть обновлены.
добавлено автор zzzzBov, источник
@JackAidley, если принятый ответ неверен, тогда кто-то, кто ищет ответ, должен поставить щедрость на существующий вопрос, а не спрашивать дубликат.
добавлено автор zzzzBov, источник
Пример: в моем коде " Decimal to Binary: Независимый размер: первый метод « Я использовал !! для преобразования int в код 0 или 1
добавлено автор Grijesh Chauhan, источник
Также обратите внимание, что этот код плохой. Задача 1: использование индекса bool as array. Проблема 2: странно !! синтаксис, который только путает читателя (как мы можем сказать из этого вопроса). Задача 3: вычисление индекса массива с ненужным сложным выражением, его нужно было перенести в собственную строку. Все эти вещи указывают на одно и то же: я подозреваю, что у нас есть программист, который считает, что они ужасно умны, но на самом деле им очень нужно узнать о правильном дизайне программ и обслуживании кода.
добавлено автор Lundin, источник
@zzzzBov: оба ответа верны. Они не дубликаты. C и C ++ обрабатывают это по-другому, дубликат указывает на правильно ответили на вопрос C ++; это правильно ответил на вопрос C. И теперь, я вижу, что вопрос правильно не отмечен как дубликат. Все хорошо в капоте.
добавлено автор Jack Aidley, источник
@zzzzBov: На самом деле я вижу, что это было отмечено как дубликат более чем одного; тот, который является now , предложенным как дубликат, является вопросом c - также правильно ответил - он был помечен как дубликат вопроса, задающего одно и то же для C ++. Разоружение царит!
добавлено автор Jack Aidley, источник
Имейте в виду, ответ Яна лучше, чем тот, что stackoverflow.com/questions/10307281/c-operator-is-a-two-not
добавлено автор Jack Aidley, источник
Ян прав, ответ на связанный дубликат неверен для C.
добавлено автор Jack Aidley, источник
добавлено автор user000001, источник
Говоря о номинации возможных дубликатов , имейте в виду, что C и C ++ являются двумя языками different . В результате я считаю, что разумно иметь два независимых вопроса с независимыми ответами. Даже если семантика схожа сегодня, будущие стандарты могут изменить это состояние.
добавлено автор Jan, источник

7 ответы

! is negation. So !! is negation of negation. What is important is the fact that the result will be an int.

  • !!x if x == 0 is !!0, that is !1, that is 0.
  • !!x if x != 0 is !!(!0), that is !!1, that is !0, that is 1.

!! is used commonly if you want to convert any non-zero value to 1 while being certain that 0 remains a 0.

И действительно, !! NULL == NULL , так как !! NULL == !! 0 и !! 0 ==! 1 и, наконец, ! 1 == 0 .

Следовательно, в коротком фрагменте кода, который вы указали, индекс массива будет либо 0 , если значение выражения в скобках NULL , а 1 в противном случае.

58
добавлено
@ShuklaSannidhya Также обратите внимание, что while !! 0 есть 0 и !! 1 есть 1 , 2 также 1 , как есть !! 3 , !! 4 , !! 5 code> ... и т. д. Он преобразует любое значение в 0 или 1.
добавлено автор David Given, источник
Я слышал !! , называемый оператором normalize .
добавлено автор David Given, источник
!! NULL никогда не должен быть предупреждением, независимо от типа NULL. ! ptr - это нормальное использование.
добавлено автор R.., источник
Результирующее значение будет либо 0 , либо 1 типа int .
добавлено автор pmg, источник
(!! NULL) == NULL является true, если NULL - 0 . Если NULL есть, скажем, ((void *) 0) , вы можете получить предупреждение сравнения с указателем на целое. Весь смысл использования !! - преобразовать результаты выражения «truey» и «falsy» в целые числа.
добавлено автор Mike DeSimone, источник
@SandyLee: Не совсем. !! false - 0 , а !! true - 1 .
добавлено автор Justin ᚅᚔᚈᚄᚒᚔ, источник
@MikeDeSimone, @pmg, спасибо, я добавил информацию о значении выражения int .
добавлено автор Jan, источник
Немного о NULL неверно ... даже если не указано предупреждение (void *) , возможно (но невероятно редко) иметь компьютер, в котором значение нулевого указателя отличное от нуля, и поэтому стандарт C позволяет NULL быть любым значением, например, может быть (void *) INT_MAX , что сделает ваше утверждение ложным. Я не уверен, какой процент кода C не смог правильно работать в такой системе, но нет необходимости побуждать людей делать это нестандартное предположение и писать более нестандартный код.
добавлено автор Theodore Murdock, источник

Обычно (ab) используется для преобразования любого значения в int s 0 или 1 путем повторного применения булевого не оператора, ! .

Например: ! 56 равен 0, поскольку 56 является «истинным», если рассматривать его как логическое. Это означает, что !! 56 равен 1, так как ! 0 равен 1.

23
добавлено
@PCLuddite Ну, я сказал, что «(ab) используется», намекая, что обвинение в злоупотреблении - это немного язык в щеке ». Я бы рекомендовал pt-> aa [(ts-> flags & MASK)! = 0] , поскольку я думаю, что это намного яснее и яснее.
добавлено автор unwind, источник
Вы говорите «злоупотребление», но это распространенная идиома. Что вы предлагаете в качестве краткой альтернативы?
добавлено автор PC Luddite, источник
это причудливо, но это не одно из худших злоупотреблений C, и определенно не одно из худших злоупотреблений на C ++. Этот язык был просто создан для злоупотребления кодом.
добавлено автор PC Luddite, источник

!E is the same as E == 0 so !!E is the same as (E == 0) == 0. !! is used to normalize booleans values.

7
добавлено

В C99 вы можете заменить его на

#include 


pt->aa[(bool)(ts->flags & MASK)] = -val;

Конечно, если ваш код будет переносимым на C89, тогда вам будет лучше делать !! Хитрость или

pt->aa[(ts->flags & MASK)!=0] = -val;

или

pt->aa[(ts->flags & MASK)?1:0] = -val;

Сгенерированный код будет, безусловно, идентичным.

4
добавлено

Он преобразует число в каноническое булево.

И обратите внимание, что в этом случае это очень важно, так как результат используется для индексации массива.

3
добавлено
  1. !!x is just a !(!x).
  2. if NULL is defined as 0 then !!NULL == !!0 == !(!0) == !(1) == 0.
2
добавлено

!! является достойным способом успокоить компилятор в определенных ситуациях, таких как назначение в условном выражении с несколькими выражениями, например:

int _blah = 100;
int *blah;
if ( _blah > 100 && !!(blah = &_blah) ) {
// do stuff
}

Я не рекомендую это - обычно предупреждают, чтобы обеспечить хорошую практику кодирования.

1
добавлено