Bagikan melalui


align (C++)

Di Visual Studio 2015 dan yang lebih baru, gunakan alignas penentu (C++11) untuk mengontrol perataan. Untuk informasi selengkapnya, lihat Perataan.

Khusus Microsoft

Gunakan __declspec(align(#)) untuk mengontrol dengan tepat penyelarasan data yang ditentukan pengguna (misalnya, alokasi statis atau data otomatis dalam fungsi).

Sintaks

__declspec( align(#) )deklarator

Keterangan

Menulis aplikasi yang menggunakan instruksi prosesor terbaru memperkenalkan beberapa batasan dan masalah baru. Banyak instruksi baru mengharuskan data diselaraskan dengan batas 16 byte. Menyelaraskan data yang sering digunakan ke ukuran baris cache prosesor meningkatkan performa cache. Misalnya, jika Anda menentukan struktur yang ukurannya kurang dari 32 byte, Anda mungkin ingin perataan 32 byte untuk memastikan bahwa objek dari jenis struktur tersebut di-cache secara efisien.

# adalah nilai perataan. Entri yang valid adalah kekuatan bilangan bulat dua dari 1 hingga 8192 (byte), seperti 2, 4, 8, 16, 32, atau 64. declarator adalah data yang Anda deklarasikan sebagai selaras.

Untuk informasi tentang cara mengembalikan nilai jenis size_t yang merupakan persyaratan perataan jenis, lihat alignof. Untuk informasi tentang cara mendeklarasikan pointer yang tidak ditandatangani saat menargetkan prosesor 64-bit, lihat __unaligned.

Anda dapat menggunakan __declspec(align(#)) saat menentukan struct, , unionatau class, atau saat Anda mendeklarasikan variabel.

Pengkompilasi tidak menjamin, atau mencoba mempertahankan, atribut perataan data selama operasi salin atau transformasi data. Misalnya, memcpy dapat menyalin struct yang dideklarasikan dengan __declspec(align(#)) ke lokasi mana pun. Alokator biasa (misalnya, , mallocC++ operator new, dan alokator Win32) biasanya mengembalikan memori yang tidak selaras untuk __declspec(align(#)) struktur atau array struktur. Untuk menjamin bahwa tujuan operasi salinan atau transformasi data diselaraskan dengan benar, gunakan _aligned_malloc. Atau, tulis alokator Anda sendiri.

Anda tidak dapat menentukan perataan untuk parameter fungsi. Saat Anda meneruskan data yang memiliki atribut perataan berdasarkan nilai pada tumpukan, konvensi panggilan mengontrol perataannya. Jika perataan data penting dalam fungsi yang disebut, salin parameter ke dalam memori yang selaras dengan benar sebelum digunakan.

Tanpa __declspec(align(#)), kompilator umumnya menyelaraskan data pada batas alami berdasarkan prosesor target dan ukuran data, hingga batas 4 byte pada prosesor 32-bit, dan batas 8-byte pada prosesor 64-bit. Data di kelas atau struktur selaras di kelas atau struktur minimal keselarasan alaminya dan pengaturan pengemasan saat ini (dari #pragma pack atau /Zp opsi pengkompilasi).

Contoh ini menunjukkan penggunaan __declspec(align(#)):

__declspec(align(32)) struct Str1{
   int a, b, c, d, e;
};

Jenis ini sekarang memiliki atribut perataan 32 byte. Ini berarti bahwa semua instans statis dan otomatis dimulai pada batas 32 byte. Jenis struktur lain yang dideklarasikan dengan jenis ini sebagai anggota mempertahankan atribut perataan jenis ini. Artinya, struktur apa pun dengan Str1 sebagai elemen memiliki atribut penyelarasan setidaknya 32.

Di sini, sizeof(struct Str1) sama dengan 32. Ini menyiratkan bahwa jika array Str1 objek dibuat, dan dasar array selaras 32 byte, setiap anggota array juga selaras 32 byte. Untuk membuat array yang basisnya diselaraskan dengan benar dalam memori dinamis, gunakan _aligned_malloc. Atau, tulis alokator Anda sendiri.

Nilai sizeof untuk struktur apa pun adalah offset anggota akhir, ditambah ukuran anggota tersebut, dibulatkan ke kelipatan terdekat dari nilai perataan anggota terbesar atau seluruh nilai perataan struktur, mana yang lebih besar.

Pengkompilasi menggunakan aturan ini untuk perataan struktur:

  • Kecuali ditimpa dengan __declspec(align(#)), penyelarasan anggota struktur skalar adalah minimum ukurannya dan pengemasan saat ini.

  • Kecuali ditimpa dengan __declspec(align(#)), penyelarasan struktur adalah maksimum penyelarasan individu anggotanya.

  • Anggota struktur ditempatkan pada offset dari awal struktur induknya yang merupakan kelipatan terkecil dari perataannya yang lebih besar dari atau sama dengan offset akhir anggota sebelumnya.

  • Ukuran struktur adalah kelipatan terkecil dari penyelarasannya lebih besar dari atau sama dengan offset akhir anggota terakhirnya.

__declspec(align(#)) hanya dapat meningkatkan pembatasan perataan.

Untuk informasi selengkapnya, lihat:

align Contoh

Contoh berikut menunjukkan bagaimana __declspec(align(#)) memengaruhi ukuran dan perataan struktur data. Contoh mengasumsikan definisi berikut:

#define CACHE_LINE  32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))

Dalam contoh ini, S1 struktur didefinisikan dengan menggunakan __declspec(align(32)). Semua penggunaan S1 untuk definisi variabel atau dalam deklarasi jenis lain selaras 32 byte. sizeof(struct S1) mengembalikan 32, dan S1 memiliki 16 byte padding setelah 16 byte yang diperlukan untuk menahan empat bilangan bulat. Setiap int anggota memerlukan penyelarasan 4 byte, tetapi keselarasan struktur itu sendiri dinyatakan 32. Kemudian penyelarasan keseluruhan adalah 32.

struct CACHE_ALIGN S1 { // cache align all instances of S1
   int a, b, c, d;
};
struct S1 s1;   // s1 is 32-byte cache aligned

Dalam contoh ini, sizeof(struct S2) mengembalikan 16, yang merupakan jumlah persis dari ukuran anggota, karena itu adalah kelipatan dari persyaratan perataan terbesar (kelipatan 8).

__declspec(align(8)) struct S2 {
   int a, b, c, d;
};

Dalam contoh berikut, sizeof(struct S3) mengembalikan 64.

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
};

Dalam contoh ini, perhatikan bahwa a memiliki keselarasan jenis alaminya, dalam hal ini, 4 byte. Namun, S1 harus selaras 32 byte. 28 byte padding mengikuti a, sehingga s1 dimulai pada offset 32. S4 kemudian mewarisi persyaratan perataan , S1karena itu adalah persyaratan penyelarasan terbesar dalam struktur. sizeof(struct S4) mengembalikan 64.

struct S4 {
   int a;
   // 28 bytes padding
   struct S1 s1;      // S4 inherits cache alignment requirement of S1
};

Tiga deklarasi variabel berikut juga menggunakan __declspec(align(#)). Dalam setiap kasus, variabel harus selaras 32 byte. Dalam array, alamat dasar array, bukan setiap anggota array, diratakan 32 byte. Nilai sizeof untuk setiap anggota array tidak terpengaruh saat Anda menggunakan __declspec(align(#)).

CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;

Untuk menyelaraskan setiap anggota array, kode seperti ini harus digunakan:

typedef CACHE_ALIGN struct { int a; } S5;
S5 array[10];

Dalam contoh ini, perhatikan bahwa menyelaraskan struktur itu sendiri dan menyelaraskan elemen pertama memiliki efek yang sama:

CACHE_ALIGN struct S6 {
   int a;
   int b;
};

struct S7 {
   CACHE_ALIGN int a;
               int b;
};

S6 dan S7 memiliki karakteristik keselarasan, alokasi, dan ukuran yang identik.

Dalam contoh ini, perataan alamat aawal , , b, cdan d masing-masing adalah 4, 1, 4, dan 1.

void fn() {
   int a;
   char b;
   long c;
   char d[10]
}

Perataan ketika memori dialokasikan pada timbunan tergantung pada fungsi alokasi mana yang dipanggil. Misalnya, jika Anda menggunakan malloc, hasilnya tergantung pada ukuran operand. Jika arg>= 8, memori yang dikembalikan diratakan 8-byte. Jika arg< 8, keselarasan memori yang dikembalikan adalah kekuatan pertama 2 kurang dari arg. Misalnya, jika Anda menggunakan malloc(7), perataannya adalah 4 byte.

Menentukan jenis baru dengan __declspec(align(#))

Anda dapat menentukan jenis dengan karakteristik perataan.

Misalnya, Anda dapat menentukan struct dengan nilai perataan dengan cara ini:

struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;

Sekarang, aType dan bType berukuran sama (8 byte) tetapi variabel jenisnya bType selaras 32 byte.

Meratakan data dalam penyimpanan lokal utas

Penyimpanan lokal utas statis (TLS) yang dibuat dengan __declspec(thread) atribut dan diletakkan di bagian TLS dalam gambar berfungsi untuk perataan persis seperti data statis normal. Untuk membuat data TLS, sistem operasi mengalokasikan memori ukuran bagian TLS dan menghormati atribut perataan bagian TLS.

Contoh ini menunjukkan berbagai cara untuk menempatkan data yang diselaraskan ke dalam penyimpanan lokal utas.

// 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;

Cara align kerja dengan pengemasan data

Opsi /Zp kompilator dan pack pragma memiliki efek mengemas data untuk anggota struktur dan serikat. Contoh ini menunjukkan cara /Zp dan __declspec(align(#)) bekerja sama:

struct S {
   char a;
   short b;
   double c;
   CACHE_ALIGN double d;
   char e;
   double f;
};

Tabel berikut ini mencantumkan offset setiap anggota di bawah nilai (atau #pragma pack) yang berbeda /Zp , memperlihatkan bagaimana keduanya berinteraksi.

Variabel /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

Untuk informasi selengkapnya, lihat /Zp (Perataan Anggota Struct).

Offset objek didasarkan pada offset objek sebelumnya dan pengaturan pengemasan saat ini, kecuali objek memiliki __declspec(align(#)) atribut, dalam hal ini perataan didasarkan pada offset objek sebelumnya dan __declspec(align(#)) nilai untuk objek.

END Khusus Microsoft

Baca juga

__declspec
Ringkasan Konvensi ABI ARM
Konvensi perangkat lunak x64