align
(C++)
Visual Studio 2015 ve sonraki sürümlerde hizalamayı denetlemek için tanımlayıcı (C++11) kullanın.alignas
Daha fazla bilgi için bkz . Hizalama.
Microsoft'a Özgü
Kullanıcı tanımlı verilerin hizalamasını hassas bir şekilde denetlemek için kullanın __declspec(align(#))
(örneğin, statik ayırmalar veya bir işlevdeki otomatik veriler).
Sözdizimi
__declspec( align( # ) ) bildirimcisi
Açıklamalar
En son işlemci yönergelerini kullanan uygulamaların yazılması bazı yeni kısıtlamalara ve sorunlara neden olur. Birçok yeni yönerge için verilerin 16 baytlık sınırlara hizalanması gerekir. Sık kullanılan verilerin işlemcinin önbellek satırı boyutuna hizalanması önbellek performansını artırır. Örneğin, boyutu 32 bayttan az olan bir yapı tanımlarsanız, bu yapı türündeki nesnelerin verimli bir şekilde önbelleğe alındığından emin olmak için 32 bayt hizalaması isteyebilirsiniz.
# hizalama değeridir. Geçerli girdiler, 1 ile 8192 (bayt) arasında iki tamsayıdır; örneğin 2, 4, 8, 16, 32 veya 64. declarator
, hizalanmış olarak bildirdiğiniz verilerdir.
Türün size_t
hizalama gereksinimi olan türde bir değeri döndürme hakkında bilgi için bkz alignof
. . 64 bit işlemcileri hedeflerken hizalanmamış işaretçileri bildirme hakkında bilgi için bkz __unaligned
. .
bir , union
veya veya tanımlarken struct
ya da class
bir değişken bildirirken kullanabilirsiniz__declspec(align(#))
.
Derleyici, kopyalama veya veri dönüştürme işlemi sırasında verilerin hizalama özniteliğini garanti etmez veya korumayı denemez. Örneğin, memcpy
ile __declspec(align(#))
bildirilen bir yapıyı herhangi bir konuma kopyalayabilir. Sıradan ayırıcılar (örneğin, malloc
, C++ operator new
ve Win32 ayırıcıları) genellikle yapılar veya yapı dizileri için __declspec(align(#))
hizalanmamış bellek döndürür. Kopyalama veya veri dönüştürme işleminin hedefinin doğru hizalandığından emin olmak için kullanın _aligned_malloc
. Ya da kendi ayırıcınızı yazın.
İşlev parametreleri için hizalama belirtemezsiniz. Yığında değere göre hizalama özniteliğine sahip verileri geçirdiğinizde, çağırma kuralı hizalamasını denetler. Çağrılan işlevde veri hizalaması önemliyse, kullanmadan önce parametresini doğru hizalanmış belleğe kopyalayın.
olmadan __declspec(align(#))
, derleyici genellikle verileri hedef işlemciye ve verilerin boyutuna göre doğal sınırlara, 32 bit işlemcilerde 4 bayt sınırlarına ve 64 bit işlemcilerde 8 bayt sınırlarına göre hizalar. Sınıflardaki veya yapılardaki veriler, doğal hizalaması ve geçerli paketleme ayarı (kimden #pragma pack
veya derleyici seçeneği) en düşük düzeyde sınıf veya yapıda /Zp
hizalanır.
Bu örnekte kullanımı gösterilmektedir __declspec(align(#))
:
__declspec(align(32)) struct Str1{
int a, b, c, d, e;
};
Bu tür artık 32 baytlık hizalama özniteliğine sahip. Bu, tüm statik ve otomatik örneklerin 32 baytlık bir sınırda başladığı anlamına gelir. Üye olarak bu türle bildirilen diğer yapı türleri, bu türün hizalama özniteliğini korur. Diğer bir ifadeyle, öğesi olarak olan Str1
herhangi bir yapı en az 32 hizalama özniteliğine sahiptir.
sizeof(struct Str1)
Burada 32'ye eşittir. Bir nesne dizisi Str1
oluşturulursa ve dizinin tabanı 32 bayt hizalanmışsa, dizinin her üyesinin de 32 bayt hizalanmış olduğu anlamına gelir. Tabanı dinamik bellekte doğru hizalanmış bir dizi oluşturmak için kullanın _aligned_malloc
. Ya da kendi ayırıcınızı yazın.
sizeof
Herhangi bir yapının değeri, en büyük üye hizalama değerinin veya tüm yapı hizalama değerinin (hangisi daha büyükse) en yakın katına yuvarlanmış, son üyenin ve bu üyenin boyutunun uzaklığıdır.
Derleyici, yapı hizalaması için şu kuralları kullanır:
ile
__declspec(align(#))
geçersiz kılınmadığı sürece, skaler yapı üyesinin hizalaması, boyutunun ve geçerli ambalajının minimum değeridir.ile
__declspec(align(#))
geçersiz kılınmadığı sürece, bir yapının hizalaması, üyelerin tek tek hizalamalarının üst sınırıdır.Yapı üyesi, hizalamasının en küçük katı olan üst yapısının başlangıcından önceki üyenin sonunun uzaklığından büyük veya buna eşit olan bir uzaklıkta yerleştirilir.
Bir yapının boyutu, hizalamasının en küçük katıdır ve son üyesinin sonunun uzaklığından büyük veya buna eşittir.
__declspec(align(#))
yalnızca hizalama kısıtlamalarını artırabilir.
Daha fazla bilgi için bkz.
align
Örnekler- ile Yeni Türler Tanımlama
__declspec(align(#))
- İş Parçacığı Yerel Depolamada Verileri Hizalama
- Veri Paketleme ile Nasıl
align
Çalışır? - x64 yapı hizalama örnekleri
align
Örnekler
Aşağıdaki örneklerde veri yapılarının boyutunu ve hizalamasını nasıl __declspec(align(#))
etkilediği gösterilmektedir. Örneklerde aşağıdaki tanımlar varsayılır:
#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))
Bu örnekte, S1
yapısı kullanılarak __declspec(align(32))
tanımlanır. Değişken tanımı veya diğer tür bildirimlerinde tüm kullanımları S1
32 bayt hizalanır. sizeof(struct S1)
32 döndürür ve S1
dört tamsayıyı tutmak için gereken 16 bayt'ı izleyen 16 doldurma baytını içerir. Her int
üye 4 bayt hizalama gerektirir, ancak yapının kendisinin hizalaması 32 olarak bildirilir. Ardından genel hizalama 32 olur.
struct CACHE_ALIGN S1 { // cache align all instances of S1
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
Bu örnekte, sizeof(struct S2)
en büyük hizalama gereksiniminin katı (8'in katı) olduğundan, üye boyutlarının toplamı olan 16 değerini döndürür.
__declspec(align(8)) struct S2 {
int a, b, c, d;
};
Aşağıdaki örnekte sizeof(struct S3)
64 döndürür.
struct S3 {
struct S1 s1; // S3 inherits cache alignment requirement
// from S1 declaration
int a; // a is now cache aligned because of s1
// 28 bytes of trailing padding
};
Bu örnekte, doğal türünün hizalamasına (bu örnekte 4 bayt) sahip olduğuna a
dikkat edin. Ancak, S1
32 bayt hizalanmış olmalıdır. 28 bayt doldurma, 32 uzaklığında başlaması için s1
öğesini izlera
. S4
ardından, yapısındaki en büyük hizalama gereksinimi S1
olduğundan hizalama gereksinimini devralır. sizeof(struct S4)
64 döndürür.
struct S4 {
int a;
// 28 bytes padding
struct S1 s1; // S4 inherits cache alignment requirement of S1
};
Aşağıdaki üç değişken bildirimi de kullanır __declspec(align(#))
. Her durumda değişken 32 bayt hizalanmış olmalıdır. Dizide, her dizi üyesi değil, dizinin temel adresi 32 bayt hizalanır. sizeof
kullandığınızda __declspec(align(#))
her dizi üyesinin değeri etkilenmez.
CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;
Bir dizinin her üyesini hizalamak için aşağıdaki gibi bir kod kullanılmalıdır:
typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];
Bu örnekte, yapının kendisini hizalamanın ve ilk öğeyi hizalamanın aynı etkiye sahip olduğuna dikkat edin:
CACHE_ALIGN struct S6 {
int a;
int b;
};
struct S7 {
CACHE_ALIGN int a;
int b;
};
S6
ve S7
aynı hizalama, ayırma ve boyut özelliklerine sahiptir.
Bu örnekte, , , b
c
ve d
başlangıç adreslerinin hizalaması a
sırasıyla 4, 1, 4 ve 1'tir.
void fn() {
int a;
char b;
long c;
char d[10]
}
Yığında bellek ayrıldığında hizalama, hangi ayırma işlevinin çağrıldığına bağlıdır. Örneğin, kullanıyorsanız malloc
sonuç işlenen boyutuna bağlıdır. arg>= 8 ise, döndürülen bellek 8 bayt hizalanır. Arg 8 ise, döndürülen belleğin hizalaması arg'den 2 küçük olan ilk güçtür.< Örneğin, kullanıyorsanız malloc(7)
hizalama 4 bayttır.
ile yeni türler tanımlama __declspec(align(#))
Hizalama özelliğine sahip bir tür tanımlayabilirsiniz.
Örneğin, hizalama değeriyle şu şekilde bir struct
tanımlayabilirsiniz:
struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;
aType
Şimdi ve bType
aynı boyutta (8 bayt) ancak türündeki bType
değişkenler 32 bayt hizalanmış.
İş parçacığı yerel depolamadaki verileri hizalama
Özniteliğiyle __declspec(thread)
oluşturulan ve görüntüdeki TLS bölümüne yerleştirilen statik iş parçacığı yerel depolama (TLS), tam olarak normal statik veriler gibi hizalama için çalışır. TLS verileri oluşturmak için, işletim sistemi belleği TLS bölümünün boyutuna ayırır ve TLS bölümü hizalama özniteliğine saygı gösterir.
Bu örnek, hizalanmış verileri iş parçacığı yerel depolama alanına yerleştirmenin çeşitli yollarını gösterir.
// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;
// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;
// create an aligned structure
struct CACHE_ALIGN S9 {
int a;
int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;
Veri paketleme ile nasıl align
çalışır?
Derleyici /Zp
seçeneği ve pack
pragması, yapı ve birleşim üyeleri için verileri paketlemenin etkisine sahiptir. Bu örnekte birlikte nasıl /Zp
ve __declspec(align(#))
birlikte çalışabilirsiniz:
struct S {
char a;
short b;
double c;
CACHE_ALIGN double d;
char e;
double f;
};
Aşağıdaki tabloda, her üyenin farklı /Zp
(veya #pragma pack
) değerleri altındaki uzaklığı listelenir ve bu iki üyenin nasıl etkileşime geçtiğini gösterir.
Değişken | /Zp1 | /Zp2 | /Zp4 | /Zp8 |
---|---|---|---|---|
a | 0 | 0 | 0 | 0 |
b | 1 | 2 | 2 | 2 |
c | 3 | 4 | 4 | 8 |
d | 32 | 32 | 32 | 32 |
e | 40 | 40 | 40 | 40 |
f | 41 | 42 | 44 | 48 |
sizeof(S) | 64 | 64 | 64 | 64 |
Daha fazla bilgi için bkz /Zp
. (Yapı Üyesi Hizalaması).
Nesnenin uzaklığı, nesnenin özniteliği __declspec(align(#))
olmadığı sürece, önceki nesnenin uzaklığı ve geçerli paketleme ayarına bağlıdır. Bu durumda hizalama, önceki nesnenin uzaklığını ve __declspec(align(#))
nesnenin değerini temel alır.
END Microsoft'a Özgü
Ayrıca bkz.
__declspec
ARM ABI Kurallarına Genel Bakış
x64 yazılım kuralları