Вопрос о макросе test_bit в C - PullRequest
       18

Вопрос о макросе test_bit в C

3 голосов
/ 19 сентября 2011

Я использовал следующий макрос в C:

#define   test_bit(_n,_p)     !! ( _n & ( 1u << _p))

Я изучил макрос, но мне нужно определить использование двойного отрицания в макросе и его поведение, отличающееся от определения макроса:

#define   test_bit(_n,_p)     ( _n & ( 1u << _p))

Ответы [ 3 ]

10 голосов
/ 19 сентября 2011

Подумайте о том, что происходит, когда вы проверяете определенный бит:

  1111 1111 (0xff)
& 0000 0100 (0x04, bit 2)
  ---- ----
= 0000 0100 (0x04)

Если вы оставите его таким, ваш результат будет самой битовой маской.

Теперь рассмотрим двойное отрицанието, что не то же самое, что ничего не делать:

!4 -> 0
!0 -> 1

Другими словами, !!4 дает вам 1 вместо 4, и это гарантирует, что вы получите0/1 истинное значение, а не 0/whatever-the-bitmask-was значение.


Следующая программа показывает это в действии:

#include <stdio.h>

#define test_bit0(_n,_p)   (_n & (1u << _p))
#define test_bit1(_n,_p) !!(_n & (1u << _p))

int main (void) {
    printf ("%d %d\n", test_bit0 (0xff, 2), test_bit1 (0xff,2));
    return 0;
}

и выдает:

4 1

, как и ожидалось.

Кроме того: в наше время очень мало мест, где вы могли бы написать такой код, поскольку современные компиляторы более чем способны автоматически встроить код и выбрать наиболее эффективный способ.сделать операцию как ((_n & (1u << _p)) != 0).И не начинайте меня с использования тупых имен переменных, использование number и position обеспечивает гораздо большую читабельность, чем во время компиляции: -)

2 голосов
/ 19 сентября 2011

По сути, целью двойного отрицания является ограничение значений, возвращаемых макросом, равными 0 и 1. В

if(test_bit(x, 5)) x=0; // (1)
array[test_bit(x, 5)] = 0; // (2)

В (1) оба определения работают одинаково.В (2) первое определение всегда устанавливает array[0] или array[1], а второе - нет.

2 голосов
/ 19 сентября 2011

Он будет вести себя по-другому, если вы связываете макрос с помощью некоторых арифметических или побитовых операторов. Например, если у вас есть

#define   test_bit(_n,_p)     ( _n & ( 1u << _p))

и

test_bit( whatever, 1 ) | test_bit( whatever, 4 )

результат будет отличаться от того, который у вас есть

#define   test_bit(_n,_p)     !! ( _n & ( 1u << _p))

А двойное отрицание - это просто другой способ написания != 0.

...