Bagikan melalui


Penjajaran

Salah satu fitur tingkat rendah C++ adalah kemampuan untuk menentukan keselarasan objek yang tepat dalam memori untuk memanfaatkan arsitektur perangkat keras tertentu secara maksimum. Secara default, kompilator menyelaraskan anggota kelas dan struktur pada nilai ukuran mereka: bool dan char pada batas 1 byte, short pada batas 2 byte, int, , longdan float pada batas 4 byte, dan long long, double, dan long double pada batas 8 byte.

Dalam kebanyakan skenario, Anda tidak perlu khawatir dengan penyelarasan karena penyelarasan default sudah optimal. Namun, dalam beberapa kasus, Anda dapat mencapai peningkatan performa yang signifikan, atau penghematan memori, dengan menentukan penyelarasan kustom untuk struktur data Anda. Sebelum Visual Studio 2015, Anda dapat menggunakan kata kunci __alignof khusus Microsoft dan __declspec(align) untuk menentukan perataan yang lebih besar dari default. Mulai dari Visual Studio 2015 Anda harus menggunakan kata kunci alignof standar C++11 dan alignas untuk portabilitas kode maksimum. Kata kunci baru bereaksi dengan cara yang sama di bawah tenda sebagai ekstensi khusus Microsoft. Dokumentasi untuk ekstensi tersebut juga berlaku untuk kata kunci baru. Untuk informasi selengkapnya, lihat alignof Operator, Penentu, alignas dan perataan. Standar C++ tidak menentukan perilaku pengemasan untuk penyelarasan pada batas yang lebih kecil dari default kompilator untuk platform target, sehingga Anda masih perlu menggunakan Microsoft #pragma pack dalam hal ini.

Gunakan kelas aligned_storage untuk alokasi memori struktur data dengan perataan kustom. Kelas aligned_union adalah untuk menentukan keselarasan untuk serikat pekerja dengan konstruktor atau destruktor nontrivial.

Perataan dan alamat memori

Perataan adalah properti alamat memori, yang dinyatakan sebagai modul alamat numerik dengan kekuatan 2. Misalnya, alamat 0x0001103F modulo 4 adalah 3. Alamat tersebut dikatakan selaras dengan 4n+3, di mana 4 menunjukkan daya 2 yang dipilih. Perataan alamat tergantung pada kekuatan 2 yang dipilih. Modul alamat yang sama 8 adalah 7. Alamat dikatakan selaras dengan X jika perataannya adalah Xn+0.

CPU menjalankan instruksi yang beroperasi pada data yang disimpan dalam memori. Data diidentifikasi oleh alamatnya dalam memori. Satu datum juga memiliki ukuran. Kami menyebut datum secara alami selaras jika alamatnya selaras dengan ukurannya. Hal ini disebut misaligned sebaliknya. Misalnya, datum floating-point 8-byte secara alami selaras jika alamat yang digunakan untuk mengidentifikasinya memiliki perataan 8 byte.

Penanganan pengompilasi perataan data

Pengkompilasi mencoba membuat alokasi data dengan cara yang mencegah ketidakselarasan data.

Untuk jenis data sederhana, pengkompilasi menetapkan alamat yang merupakan kelipatan ukuran dalam byte jenis data. Misalnya, pengkompilasi menetapkan alamat ke variabel jenis long yang merupakan kelipatan 4, mengatur 2 bit bawah alamat ke nol.

Pengkompilasi juga menyatukan struktur dengan cara yang secara alami menyelaraskan setiap elemen struktur. Pertimbangkan struktur struct x_ dalam contoh kode berikut:

struct x_
{
   char a;     // 1 byte
   int b;      // 4 bytes
   short c;    // 2 bytes
   char d;     // 1 byte
} bar[3];

Pengkompilasi melengkapi struktur ini untuk menegakkan keselarasan secara alami.

Contoh kode berikut menunjukkan bagaimana pengkompilasi menempatkan struktur padded dalam memori:

// Shows the actual memory layout
struct x_
{
   char a;            // 1 byte
   char _pad0[3];     // padding to put 'b' on 4-byte boundary
   int b;            // 4 bytes
   short c;          // 2 bytes
   char d;           // 1 byte
   char _pad1[1];    // padding to make sizeof(x_) multiple of 4
} bar[3];

Kedua deklarasi kembali sizeof(struct x_) sebagai 12 byte.

Deklarasi kedua mencakup dua elemen padding:

  1. char _pad0[3] untuk menyelaraskan int b anggota pada batas 4 byte.
  2. char _pad1[1] untuk menyelaraskan elemen array struktur struct _x bar[3]; pada batas 4 byte.

Padding menyelaraskan elemen bar[3] dengan cara yang memungkinkan akses alami.

Contoh kode berikut menunjukkan bar[3] tata letak array:

adr offset   element
------   -------
0x0000   char a;         // bar[0]
0x0001   char pad0[3];
0x0004   int b;
0x0008   short c;
0x000a   char d;
0x000b   char _pad1[1];

0x000c   char a;         // bar[1]
0x000d   char _pad0[3];
0x0010   int b;
0x0014   short c;
0x0016   char d;
0x0017   char _pad1[1];

0x0018   char a;         // bar[2]
0x0019   char _pad0[3];
0x001c   int b;
0x0020   short c;
0x0022   char d;
0x0023   char _pad1[1];

alignof dan alignas

Penentu alignas adalah cara standar C++ portabel untuk menentukan perataan kustom variabel dan jenis yang ditentukan pengguna. Operator alignof juga merupakan cara portabel standar untuk mendapatkan penyelarasan jenis atau variabel tertentu.

Contoh

Anda dapat menggunakan alignas pada kelas, struct atau union, atau pada masing-masing anggota. Ketika beberapa alignas penentu ditemui, pengkompilasi memilih yang memiliki nilai terbesar.

// alignas_alignof.cpp
// compile with: cl /EHsc alignas_alignof.cpp
#include <iostream>

struct alignas(16) Bar
{
    int i;       // 4 bytes
    int n;      // 4 bytes
    alignas(4) char arr[3];
    short s;          // 2 bytes
};

int main()
{
    std::cout << alignof(Bar) << std::endl; // output: 16
}

Baca juga

Perataan struktur data