2013-06-13 40 views
36

Tôi làm việc với bộ nhớ dùng chung ngay bây giờ.Sắp xếp bộ nhớ: cách sử dụng alignof/alignas?

Tôi không thể hiểu được alignofalignas.

cppreference không rõ ràng: alignof trả về "căn chỉnh" nhưng "căn chỉnh" là gì? số byte để thêm cho khối tiếp theo được căn chỉnh? đệm kích thước? Stack overflow/blog mục không rõ ràng quá.

Ai đó có thể giải thích rõ ràng alignofalignas?

+1

cppreference đang cố gắng trở thành tham chiếu thay vì hướng dẫn – Cubbi

+0

@Cubbi: bạn cũng có thể kiểm tra tại cplusplus.com, có tranh luận về trang web tốt hơn, đối với một số chủ đề nhất định, tốt hơn, tôi đã tìm thấy cppreference cả hai trang web nhất định không phải là eonugh – GameDeveloper

+1

@DarioOO Tôi chỉ trả lời tại sao cppreference không giải thích khái niệm căn lề trên trang 'alignof' (hiện tại, trên trang đối tượng [work-in-progress] (http: //en.cppreference.com/w/cpp/language/object#Alignment)). Tôi không thấy cplusplus.com có ​​liên quan như thế nào. – Cubbi

Trả lời

36

Alignment là một hạn chế mà bộ nhớ vị trí byte đầu tiên của một giá trị có thể được lưu trữ . (Nó là cần thiết để cải thiện hiệu suất trên bộ vi xử lý và cho phép sử dụng các hướng dẫn nhất định chỉ hoạt động trên dữ liệu có căn chỉnh cụ thể, ví dụ SSE cần được căn chỉnh đến 16 byte, trong khi AVX đến 32 byte.)

Căn chỉnh 16 có nghĩa là địa chỉ bộ nhớ là bội số của 16 là địa chỉ hợp lệ duy nhất.

alignas 

lực liên kết để yêu cầu số lượng byte (cppreference không đề cập đến nó, nhưng tôi nghĩ rằng bạn chỉ có thể sắp xếp để lũy thừa của 2: 1, 2, 4, 8, 16, 32, 64, 128,. ..)

#include <cstdlib> 
#include <iostream> 

int main() { 
    alignas(16) int a[4]; 
    alignas(1024) int b[4]; 
    printf("%p\n", a); 
    printf("%p", b); 
} 

dụ đầu ra:

0xbfa493e0 
0xbfa49000 // note how many more "zeros" now. 
// binary equivalent 
1011 1111 1010 0100 1001 0011 1110 0000 
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2 

từ khóa khác

alignof 

là rất thuận tiện, bạn không thể làm một cái gì đó giống như

int a[4]; 
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error 

nhưng bạn có thể làm

01.235.
assert(alignof(a) == 16); 
assert(alignof(b) == 1024); 

lưu ý rằng trong thực tế, điều này nghiêm ngặt hơn hoạt động "%" (mô đun) đơn giản. Trong thực tế chúng ta biết rằng một cái gì đó liên kết đến 1024 byte được thiết liên kết đến 1, 2, 4, 8 byte nhưng

assert(alignof(b) == 32); // fail. 

Vì vậy, để được chính xác hơn, "alignof" trả về sức mạnh vĩ đại nhất từ ​​2 đến Mà một cái gì đó là liên kết .

Cũng alignof là một cách tốt đẹp để biết trước yêu cầu căn chỉnh tối thiểu cho các kiểu dữ liệu cơ bản (nó có thể sẽ trả về 1 cho ký tự, 4 cho float vv).

Tuy nhiên pháp luật:

alignas(alignof(float)) float SqDistance; 

Something với một liên kết của 16 sau đó sẽ được đặt trên các địa chỉ có sẵn tiếp theo đó là một bội số của 16 (có thể có một lớp đệm ngầm từ địa chỉ sử dụng cuối cùng).

+6

Không giống' sizeof', 'alignof' chỉ có thể được áp dụng cho' type-id'. – neverhoodboy

+0

là 'alignof()' (và đối số 'alignas()') được đánh giá tại thời gian biên dịch, vì vậy không có chi phí thời gian chạy? – nonsensation

+0

không. Nó là không thể, trình biên dịch có thể làm điều đó như tối ưu hóa trong rất ít trường hợp, nhưng nói chung nó sẽ không biết làm thế nào địa chỉ bộ nhớ được sắp xếp trước khi đánh giá 2 chức năng. Chỉ cần nhìn vào lắp ráp được tạo ra bởi ví dụ của tôi: http://goo.gl/ZbemBF – GameDeveloper

5

Căn chỉnh không phải là đệm (mặc dù đệm đôi khi được giới thiệu để đáp ứng yêu cầu căn chỉnh). Nó là một thuộc tính intrisic của một kiểu C++. Để đặt nó theo tiêu chuẩn (3.11[basic.align])

Loại đối tượng có yêu cầu căn chỉnh (3.9.1, 3.9.2) giới hạn địa điểm mà tại đó một đối tượng thuộc loại đó có thể được phân bổ. Một liên kết là một giá trị số nguyên được xác định thực hiện đại diện cho số byte giữa các địa chỉ kế tiếp mà tại đó một đối tượng nhất định có thể được cấp phát. Một kiểu đối tượng áp đặt một yêu cầu căn chỉnh trên mọi đối tượng thuộc loại đó; liên kết chặt chẽ hơn có thể được yêu cầu bằng cách sử dụng bộ định vị căn chỉnh (7.6.2).

+1

Rất thú vị. Bạn có phiền không khi đưa ra một số ví dụ? Có alignof (struct X) == sizeof (struct X)? Tại sao không ? – Offirmo

+1

@Offirmo no, ngoại trừ bởi concidence: 'struct X {char a; char b} 'có kích thước 2 và yêu cầu căn chỉnh 1, trên các hệ thống sane (nó có thể được cấp phát tại bất kỳ địa chỉ nào vì char có thể được cấp phát tại bất kỳ địa chỉ nào) – Cubbi

+0

req liên kết của 1 ???? Oh tôi hiểu rồi: Tôi nghĩ rằng sự liên kết luôn luôn ở ranh giới "tự nhiên" 32bits/64bit nhưng rõ ràng là không. Điều đó giải thích mọi thứ ... Vì vậy, trên các máy thông thường, kết quả alignof() sẽ luôn tối đa ở mức 4 (32bits) hoặc 8 (64bits) Tôi có đúng không? – Offirmo

3

Mỗi loại có yêu cầu căn chỉnh. Nói chung, đây là các biến của loại có thể được truy cập hiệu quả, mà không cần phải gây ra CPU để tạo ra nhiều hơn một truy cập đọc/ghi để tiếp cận bất kỳ thành viên nào của kiểu dữ liệu. Hơn nữa, nó cũng đảm bảo sao chép hiệu quả của toàn bộ biến. alignof sẽ trả về yêu cầu căn chỉnh cho loại đã cho.

alignas được sử dụng để buộc một liên kết trên một datatype (miễn là nó không phải là ít nghiêm ngặt rằng những gì alignof nói datatype sẽ quay trở lại)

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