2012-10-29 39 views
9

Tôi không thể hiểu macro này làm gì. Chúng được định nghĩa trong linux-kernel nhưng tôi nghi ngờ của tôi là độc lập với điều đó. Tôi không thể hiểu được những gì hiện (((x)+(mask))&~(mask)) dòng nào.căn chỉnh hạt nhân macro

#define ALIGN(x,a)    __ALIGN_MASK(x,(typeof(x))(a)-1) 
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) 

Mọi trợ giúp đều được đánh giá cao.

Trả lời

19

Giả sử bạn có một số lượng: 0x1006

Vì một số lý do bạn muốn căn chỉnh nó thành ranh giới 4 byte. giá trị

Với một ranh giới 4-byte, bạn biết liên kết là 0x1000, 0x1004, 0x1008 vv Sau đó, bạn cũng biết giá trị liên kết của 0x10060x1008.

Làm cách nào để nhận được 0x1008? Mặt nạ liên kết cho giá trị liên kết 4(4 - 1) = 0x03

Bây giờ 0x1006 + 0x03 = 0x10090x1009 & ~0x03 = 0x1008

Thao tác này là __ALIGN_MASK vĩ mô.

Nếu bạn muốn vượt qua giá trị 4 (sự liên kết) thay vì trực tiếp 0x03 (mặt nạ alignment), bạn có các ALIGN vĩ mô

11
#define ALIGN(x,a)    __ALIGN_MASK(x,(typeof(x))(a)-1) 

sự liên kết, a, được đúc để loại x 's, và sau đó ai được trừ. Căn chỉnh phải là công suất 2, do đó, kết quả là một số mẫu bit 00..011..11 của loại x, mặt nạ (k 1s nếu a = 2^k).

Sau đó

#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) 

thêm giá trị của mặt nạ để x, do đó (x)+ (mask) ít nhất là lớn như nhiều nhỏ nhất của sự liên kết đó không phải là nhỏ hơn x và nhỏ hơn nhiều lớn hơn tiếp theo. Sau đó, bitwise và với sự bổ sung của mặt nạ làm giảm số đó đến bội số của căn chỉnh đó.

Đối với mặt nạ dạng 2^k - 1, việc tính toán

(x + mask) & ~mask 

cũng giống như

(x + 2^k - 1) - ((x + 2^k - 1) % (2^k)) 

hoặc

((x + 2^k - 1)/(2^k)) * (2^k) 
+0

Liệu điều này làm việc lừa cho 'alignment' mà không phải là sức mạnh của 2. –

+0

Không, nó chỉ hoạt động với các quyền hạn của 2. Nhưng việc chỉ định căn chỉnh chỉ hữu ích cho các quyền hạn của 2, vì vậy không có trường hợp hữu ích nào bị xử lý sai. –

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