Aracılığıyla paylaş


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 , unionveya veya tanımlarken structya da classbir 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 newve 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

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 S1olduğ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, , , bcve d başlangıç adreslerinin hizalaması ası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 mallocsonuç 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ı