2012-01-19 35 views
17

Tôi muốn một hàm C đơn giản sẽ trả về true nếu bit thứ n trong một byte được đặt thành 1. Nếu không, nó sẽ trả về false.một chức năng để kiểm tra xem bit thứ n được đặt trong một byte

Đây là một chức năng quan trọng về thời gian thực hiện, vì vậy tôi đang nghĩ đến cách tối ưu nhất để thực hiện điều đó.

+1

trùng lặp, http://stackoverflow.com/questions/523724/cc-check-if-one-bit-is -set-in-ie-int-variable – blueshift

+4

Đó không phải là một bản dupe, nó được hỏi cụ thể về các phương thức ** non-bitshift **. – paxdiablo

Trả lời

32

Chức năng sau đây có thể làm những gì bạn cần:

int isNthBitSet (unsigned char c, int n) { 
    static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1}; 
    return ((c & mask[n]) != 0); 
} 

này giả byte 8-bit (không phải là đưa ra trong C) và các bit 0 là thứ tự cao nhất. Nếu giả định đó không chính xác, nó chỉ đơn giản là đi xuống để mở rộng và/hoặc sắp xếp lại mảng mask.

Không kiểm tra lỗi được thực hiện vì bạn đã trích dẫn tốc độ là yếu tố quan trọng nhất. Làm không phải chuyển vào một số n không hợp lệ, đó sẽ là hành vi không xác định.

Ở cấp độ tối ưu hóa điên -O3, gcc cho chúng ta:

isNthBitSet: pushl %ebp 
       movl %esp, %ebp 
       movl 12(%ebp), %eax 
       movzbl 8(%ebp), %edx 
       popl %ebp 
       testb %dl, mask(%eax) 
       setne %al 
       movzbl %al, %eax 
       ret 
mask:   .byte -128, 64, 32, 16, 8, 4, 2, 1 

mà là khá nhỏ và hiệu quả. Và nếu bạn làm cho nó tĩnh và đề xuất nội tuyến, hoặc buộc nội tuyến là định nghĩa macro, bạn thậm chí có thể bỏ qua chi phí của một cuộc gọi hàm.

Chỉ cần đảm bảo bạn đánh giá mọi giải pháp mà bạn được cung cấp, bao gồm giải pháp này (a). Câu thần chú số một trong tối ưu hóa là "Đo lường, đừng đoán!"

Nếu bạn muốn biết cách các toán tử bitwise hoạt động, hãy xem here. Phiên bản AND chỉ đơn giản hóa bên dưới.

Thao tác AND & sẽ đặt bit chỉ trong mục tiêu nếu cả hai bit được đặt trong nguồn tewo. Bảng có liên quan là:

AND | 0 1 
----+---- 
0 | 0 0 
1 | 0 1 

Đối với một giá trị char nhất định, chúng tôi sử dụng các mặt nạ đơn chút chút để kiểm tra xem một chút được thiết lập. Giả sử bạn có giá trị 13 và bạn muốn xem liệu bit thứ ba từ ít quan trọng nhất có được đặt hay không.

Decimal Binary 
    13  0000 1101 
    4  0000 0100 (the bitmask for the third-from-least bit). 
     ========= 
     0000 0100 (the result of the AND operation). 

Bạn có thể thấy rằng tất cả các bit không trong mặt nạ dẫn đến các bit kết quả tương đương bằng không. Một bit duy nhất trong mặt nạ về cơ bản sẽ cho bit tương đương trong luồng giá trị thông qua kết quả. Kết quả là 0 nếu bit chúng ta kiểm tra bằng không, hoặc khác 0 nếu nó là một.

Đó là nơi biểu thức trong câu lệnh return xuất phát từ đó. Các giá trị trong bảng tra cứu mask là tất cả các mặt nạ đơn-bit:

Decimal Binary 
    128 1000 0000 
    64 0100 0000 
    32 0010 0000 
    16 0001 0000 
    8 0000 1000 
    4 0000 0100 
    2 0000 0010 
    1 0000 0001 

(a)tôi biết tôi như thế nào tốt, nhưng bạn không :-)

+2

Bảng tra cứu, vâng! Nhưng tôi mong đợi bit 0 là bit có ý nghĩa ít nhất trong byte, và do đó sẽ đảo ngược thứ tự của các mục nhập 'mask []' intialized. – hardmath

+0

Không phải lúc nào, @hardmath, rất nhiều tiêu chuẩn comms điền octet của họ từ "trái". Giống như bạn, tôi thích suy nghĩ của b0 là ít quan trọng nhất. – paxdiablo

+0

-1, chi tiết và dễ bị lỗi khi viết, tìm hiểu về dịch chuyển bit. – blueshift

20

Chỉ cần kiểm tra giá trị (1 << bit) & byte. Nếu nó không phải là nonzero, bit được thiết lập.

3
bool isSet(unsigned char b, unsigned char n) { return b & (1 << n); } 
+0

Tôi hiểu 'unsigned char' cho giá trị byte, nhưng' n'? Điều đó có vẻ kỳ quặc. – Rob

+0

cũng n không thể lớn hơn một byte ... nó không thực sự quan trọng nhiều –

+0

Vì 'unsigned char' không hạn chế n chỉ giá trị hợp lệ, tôi sẽ cho rằng đó là một [nhỏ]" mã mùi "liên quan để dễ đọc. Tất nhiên, đó là điều gây tranh cãi và tôi sẽ đồng ý nó không quan trọng lắm. – Rob

8

Cho số là num. Sau đó:

return ((1 << n) & num); 
+0

Bạn có thể giải thích mã này không? – vidyasagarr7

2
#include<stdio.h> 
int main() 
{ 
    unsigned int n,a; 
    printf("enter value for n\n"); 
    scanf("%u",&n); 
    pintf("enter value for a:\n"); 
    scanf("%u",&a); 
    a= a|(((~((unsigned)0))>>(sizeof(int)*8-1))<<n); 
    printf("%u\n",a); 
} 
2

cách tiếp cận khác sẽ

bool isNthBitSet (unsigned char c, int n) { 
     return (1 & (c >> n)); 
    } 
0
#include<stdio.h> 

int main() 
{ 
     int data,bit; 
     printf("enter data:"); 
     scanf("%d",&data); 
     printf("enter bit position to test:"); 
     scanf("%d",&bit); 
     data&(1<<bit)?printf("bit is set\n"):printf("bit is clear\n"); 

    return 0; 
} 
+2

Mã chỉ giải đáp này yêu cầu một số giải thích để làm cho giá trị gia tăng rõ ràng hơn, so sánh với các câu trả lời khác, cũ hơn, upvoted và tốt hơn (không ngụ ý rằng tất cả các câu trả lời khác được giải thích rõ hơn ...). – Yunnosch

Các vấn đề liên quan