Các phép toán bitwise
Đôi khi bạn có thể cần xử lý số ở cấp độ bit. Vì mục đích này, có một nhóm các phép toán bitwise áp dụng cho các kiểu số nguyên.
Tất cả các ký hiệu và mô tả về toán tử bitwise đều được cung cấp cùng với khả năng kết hợp và thứ tự ưu tiên của chúng trong bảng dưới đây.
P | Biểu tượng | Mô tả | Ví dụ | A |
---|---|---|---|---|
2 | ~ | Bổ sung bitwise (đảo ngược) | ~e1 | R |
5 | << | Dịch sang trái | e1 << e2 | L |
5 | >> | Dịch sang phải | e1 >> e2 | L |
8 | & | AND bitwise | e1 & e2 | L |
9 | ^ | OR bitwise loại trừ | e1 ^ e2 | L |
10 | | | OR bitwise | e1 | e2 | L |
Trong toàn bộ nhóm, chỉ có phép toán bổ sung bit ~
là phép toán đơn ngôi, trong khi tất cả các phép toán khác đều là phép toán nhị phân (hai ngôi).
Trong mọi trường hợp, nếu kích thước toán hạng nhỏ hơn int/uint
, nó được mở rộng sơ bộ thành int / uint
bằng cách thêm 0 bit
vào bậc cao hơn. Dựa trên loại toán hạng là có dấu/không dấu, một bit bậc cao có thể ảnh hưởng đến dấu.
Ứng dụng Windows chuẩn, Máy tính, có thể giúp hiểu cách biểu diễn số ở cấp độ bit. Nếu bạn chọn chế độ hoạt động Lập trình viên trong menu View
, các nhóm nút chuyển đổi sẽ xuất hiện trong chương trình để chọn cách biểu diễn số ở dạng thập lục phân (Hex
), thập phân (Dec
), bát phân (Oct
) hoặc nhị phân (Bin
). Dạng sau hiển thị các bit. Hơn nữa, bạn có thể chọn kích thước số: 1
, 2
, 4
và 8
byte. Các nút cho phép thực hiện tất cả các phép toán được xem xét: Không (~
), Và (&
), Hoặc (|
), Xor (^
), Lsh (<<
) và Rsh (>>
).
Vì Máy tính sử dụng số có dấu, nên các giá trị âm có thể xuất hiện khi chuyển sang chế độ thập phân (hãy nhớ rằng bit bậc cao được hiểu là dấu). Để phân tích thuận tiện, nên loại trừ dấu trừ xuất hiện, vì mục đích này, cần phải chọn kích thước tính bằng byte cao hơn một bậc. Ví dụ, để kiểm tra các giá trị trong phạm vi lên đến 255 (uchar
, số nguyên một byte không dấu), bạn nên chọn 2 byte (nếu không, chỉ các giá trị thập phân đến 127 mới là dương, trong khi các giá trị khác sẽ được hiển thị ở vùng âm).
Bổ sung bitwise tạo ra một giá trị, trong đó bit 0 thay thế cho tất cả các bit 1, trong khi bit 1 thay thế cho các bit 0. Ví dụ, phủ định một byte với tất cả các bit 0 sẽ tạo ra một byte với tất cả các bit 1. Số 50 xuất hiện ở định dạng bitwise
là '00110010' (byte). Đảo ngược của nó sẽ tạo ra '11001101'.
Unity được biểu diễn dưới dạng thập lục phân là 0x0001
(viết tắt). Đảo ngược các bit này sẽ cho kết quả là 0xFFFE
(xem tập lệnh ExprBitwise.mq5
).
short v = ~1; // 0xfffe = -2
ushort w = ~1; // 0xfffe = 65534
2
Bitwise AND kiểm tra từng bit trong cả hai toán hạng và ở các vị trí tìm thấy hai bit set (1), lưu bit 1 vào kết quả. Trong tất cả các trường hợp khác (khi chỉ có một bit set trong một toán hạng hoặc chúng được đặt lại ở cả hai vị trí), bit 0 được ghi vào kết quả.
Bitwise OR ghi các bit 1 vào kết quả nếu chúng nằm ở vị trí có bit set trong ít nhất một trong hai toán hạng.
Phép toán OR loại trừ bit ghi vào kết quả các bit 1 ở các vị trí có bit set trong toán hạng thứ nhất hoặc thứ hai, nhưng không phải ở cả hai cùng một lúc. Biểu diễn nhị phân của hai số X và Y, và kết quả của các phép toán bit với chúng được hiển thị bên dưới.
X 10011010 154
Y 00110111 55
X & Y 00010010 18
X | Y 10111111 191
X ^ Y 10101101 173
2
3
4
5
6
Khi viết các biểu thức phức tạp từ nhiều toán tử khác nhau, hãy sử dụng nhóm trong dấu ngoặc đơn để không bị nhầm lẫn với thứ tự ưu tiên.
Các phép dịch chuyển di chuyển các bit sang trái (<<
) hoặc sang phải (>>
) theo số lượng bit, được xác định trong toán hạng thứ hai phải là một số nguyên không âm. Kết quả là, các bit trái (cho <<
) hoặc phải (cho >>
) bị loại bỏ, vì chúng vượt ra ngoài ranh giới ô nhớ. Với phép dịch chuyển trái, số bit 0 có liên quan được thêm vào bên phải. Với phép dịch chuyển phải, hoặc là các bit 0 được thêm vào bên trái (nếu toán hạng không dấu) hoặc bit dấu được tái tạo (nếu toán hạng có dấu). Trong trường hợp sau, các bit 0 được thêm vào bên trái đối với các số dương và các bit 1 đối với các số âm; tức là, dấu được giữ nguyên.
short q = v << 5; // 0xffc0 = -64
ushort p = w << 5; // 0xffc0 = 65472
short r = q >> 5; // 0xfffe = -2
ushort s = p >> 5; // 0x07fe = 2046
2
3
4
Trong ví dụ trên, phép dịch chuyển trái ban đầu đã "phá hủy" các bit bậc cao của biến p , trong khi phép dịch chuyển phải tiếp theo với cùng số lượng bit đã điền chúng bằng số không, dẫn đến việc giảm giá trị từ 0xffc0
xuống 0x07fe
.
Kích thước dịch chuyển (số lượng bit) phải nhỏ hơn kích thước của kiểu toán hạng (xem xét khả năng mở rộng tiềm ẩn của nó). Nếu không, tất cả các bit ban đầu sẽ bị mất.
Dịch chuyển 0 bit sẽ giữ nguyên số đó.
Các phép toán bit &
và |
không nên được kết hợp với các phép toán logic &&
và ||
(đã được xem xét ở phần trước).