Mempertimbangkan:
struct mystruct_A
{
char a;
int b;
char c;
} x;
struct mystruct_B
{
int b;
char a;
} y;
Ukuran struktur masing-masing adalah 12 dan 8.
Apakah struktur ini empuk atau dikemas?
Kapan bantalan atau pengemasan berlangsung?
padding
membuat segalanya lebih besar.packing
membuat segalanya lebih kecil. Benar-benar berbeda.Jawaban:
Padding menyelaraskan anggota struktur ke batas alamat "alami" - katakanlah,
int
anggota akan memiliki offset, yang adamod(4) == 0
di platform 32-bit. Padding aktif secara default. Ini memasukkan "celah" berikut ke dalam struktur pertama Anda:Pengepakan , di sisi lain mencegah kompiler melakukan padding - ini harus diminta secara eksplisit - di bawah GCC itu
__attribute__((__packed__))
, jadi yang berikut:akan menghasilkan struktur ukuran
6
pada arsitektur 32-bit.Namun catatan - akses memori yang tidak selaras lebih lambat pada arsitektur yang memungkinkannya (seperti x86 dan amd64), dan secara eksplisit dilarang pada arsitektur penyelarasan ketat seperti SPARC.
sumber
( Jawaban di atas menjelaskan alasannya dengan cukup jelas, tetapi tampaknya tidak sepenuhnya jelas tentang ukuran bantalan, jadi, saya akan menambahkan jawaban sesuai dengan apa yang saya pelajari dari The Lost Art of Structure Packing , telah berevolusi menjadi tidak terbatas pada
C
, tetapi juga berlaku untukGo
,Rust
. )Perataan memori (untuk struct)
Aturan:
misalnya pada sistem 64 bit,
int
harus dimulai pada alamat yang dapat dibagi dengan 4, danlong
oleh 8,short
dengan 2.char
danchar[]
istimewa, bisa berupa alamat memori apa pun, sehingga tidak perlu diisi sebelumnya.struct
, selain kebutuhan pelurusan untuk setiap anggota individu, ukuran seluruh struct itu sendiri akan disejajarkan dengan ukuran yang dapat dibagi berdasarkan ukuran anggota individu terbesar, dengan melapisi bagian ujungnya.misalnya jika anggota struct terbesar adalah
long
kemudian dapat dibagi 8,int
kemudian oleh 4,short
kemudian oleh 2.Urutan anggota:
stu_c
danstu_d
dari contoh di bawah ini memiliki anggota yang sama, tetapi dalam urutan yang berbeda, dan menghasilkan ukuran yang berbeda untuk 2 struct.Alamat dalam memori (untuk struct)
Aturan:
alamat Struct dimulai dari
(n * 16)
byte. ( Anda dapat melihat pada contoh di bawah ini, semua alamat hex yang dicetak dari structs berakhir dengan0
. )Alasan : anggota struct individu terbesar yang mungkin adalah 16 byte (
long double
).char
sebagai, alamatnya dapat dimulai dari alamat mana pun.Ruang kosong :
Misalnya di
test_struct_address()
bawah, variabelx
berada di antara struct yang berdekatang
danh
.Tidak peduli apakah
x
dinyatakan,h
alamat tidak akan berubah,x
cukup gunakan kembali ruang kosong yangg
terbuang.Kasus serupa untuk
y
.Contoh
( untuk sistem 64 bit )
memory_align.c :
Hasil eksekusi -
test_struct_padding()
:Hasil eksekusi -
test_struct_address()
:Dengan demikian alamat mulai untuk setiap variabel adalah g: d0 x: dc h: e0 y: e8
sumber
<The Lost Art of C Structure Packing>
, menjelaskan aturan dengan cukup baik, bahkan berpikir itu sedikit lebih lama dari jawaban ini. Buku ini tersedia gratis secara online: catb.org/esr/structure-packingSaya tahu pertanyaan ini sudah tua dan sebagian besar jawaban di sini menjelaskan padding dengan sangat baik, tetapi ketika mencoba memahaminya sendiri, saya pikir memiliki gambar "visual" tentang apa yang terjadi membantu.
Prosesor membaca memori dalam "potongan" dengan ukuran yang pasti (kata). Ucapkan kata prosesor sepanjang 8 byte. Ini akan melihat memori sebagai deretan besar blok bangunan 8 byte. Setiap kali perlu mendapatkan beberapa informasi dari memori, itu akan mencapai salah satu blok dan mendapatkannya.
Seperti tampak pada gambar di atas, tidak masalah di mana Char (panjang 1 byte) berada, karena akan berada di dalam salah satu blok itu, membutuhkan CPU untuk memproses hanya 1 kata.
Ketika kita berurusan dengan data yang lebih besar dari satu byte, seperti 4 byte int atau 8 byte ganda, cara mereka disejajarkan dalam memori membuat perbedaan pada berapa banyak kata yang harus diproses oleh CPU. Jika potongan 4-byte disejajarkan dengan cara mereka selalu cocok dengan bagian dalam blok (alamat memori menjadi kelipatan 4) hanya satu kata yang harus diproses. Kalau tidak, sepotong 4-byte dapat memiliki bagian dari dirinya sendiri di satu blok dan bagian lain, yang membutuhkan prosesor untuk memproses 2 kata untuk membaca data ini.
Hal yang sama berlaku untuk ganda 8-byte, kecuali sekarang itu harus dalam kelipatan alamat memori 8 untuk menjamin itu akan selalu berada di dalam blok.
Ini mempertimbangkan pengolah kata 8-byte, tetapi konsep ini berlaku untuk ukuran kata lain.
Padding berfungsi dengan mengisi celah di antara data tersebut untuk memastikan mereka sejajar dengan blok-blok itu, sehingga meningkatkan kinerja saat membaca memori.
Namun, seperti yang dinyatakan pada jawaban orang lain, terkadang ruang lebih penting daripada kinerja itu sendiri. Mungkin Anda sedang memproses banyak data di komputer yang tidak memiliki banyak RAM (ruang swap dapat digunakan tetapi jauh lebih lambat). Anda dapat mengatur variabel-variabel dalam program sampai padding paling tidak selesai (seperti yang sangat dicontohkan dalam beberapa jawaban lain) tetapi jika itu tidak cukup Anda dapat secara eksplisit menonaktifkan padding, yang merupakan pengemasan .
sumber
Packing struktur menekan padding struktur, padding digunakan saat pelurusan paling penting, packing digunakan saat ruang paling penting.
Beberapa kompiler menyediakan
#pragma
untuk menekan padding atau membuatnya dikemas ke sejumlah byte. Beberapa menyediakan kata kunci untuk melakukan ini. Secara umum pragma yang digunakan untuk memodifikasi padding struktur akan dalam format di bawah ini (tergantung pada kompiler):Misalnya ARM menyediakan
__packed
kata kunci untuk menekan padding struktur. Bacalah manual kompiler Anda untuk mempelajari lebih lanjut tentang ini.Jadi struktur yang dikemas adalah struktur tanpa bantalan.
Struktur yang dikemas umumnya akan digunakan
untuk menghemat ruang
untuk memformat struktur data untuk mentransmisikan melalui jaringan menggunakan beberapa protokol (ini bukan praktik yang baik tentu saja karena Anda harus
berurusan dengan endianness)
sumber
Padding dan packing hanyalah dua aspek dari hal yang sama:
Dalam
mystruct_A
, dengan asumsi penyelarasan default 4, setiap anggota disejajarkan pada kelipatan 4 byte. Karena ukurannyachar
adalah 1, padding untuka
danc
4 - 1 = 3 byte sedangkan padding tidak diperlukan untukint b
yang sudah 4 byte. Cara kerjanya sama untukmystruct_B
.sumber
Pengepakan struktur hanya dilakukan ketika Anda memberi tahu kompiler Anda secara eksplisit untuk mengemas struktur. Padding adalah apa yang Anda lihat. Sistem 32-bit Anda mengisi setiap bidang dengan perataan kata. Jika Anda telah memberitahu kompiler Anda untuk mengemas struktur, mereka akan menjadi 6 dan 5 byte, masing-masing. Jangan lakukan itu. Ini tidak portabel dan membuat kompiler menghasilkan kode lebih lambat (dan kadang-kadang bahkan buggy).
sumber
Tidak ada yang lain selain itu! Yang ingin memahami subjek harus melakukan hal-hal berikut,
sumber
Aturan untuk bantalan:
Mengapa Aturan 2: Pertimbangkan struct berikut,
Jika kami membuat array (terdiri dari 2 struct) dari struct ini, Padding tidak diperlukan di akhir:
Oleh karena itu, ukuran struct = 8 byte
Asumsikan kita akan membuat struct lain seperti di bawah ini:
Jika kita membuat array dari struct ini, ada 2 kemungkinan, dari jumlah byte padding yang diperlukan di akhir.
A. Jika kita menambahkan 3 byte di akhir dan sejajarkan untuk int dan bukan Long:
B. Jika kita menambahkan 7 byte di akhir dan sejajarkan untuk Long:
Alamat awal array kedua adalah kelipatan 8 (yaitu 24). Ukuran struct = 24 byte
Oleh karena itu, dengan menyelaraskan alamat mulai dari array berikutnya dari struct ke beberapa anggota terbesar (yaitu jika kita ingin membuat array dari struct ini, alamat pertama dari array kedua harus dimulai pada alamat yang merupakan beberapa dari anggota terbesar dari struct. Ini dia, 24 (3 * 8)), kita dapat menghitung jumlah byte padding yang dibutuhkan di akhir.
sumber
Penyelarasan struktur data adalah cara data disusun dan diakses dalam memori komputer. Ini terdiri dari dua masalah yang terpisah tetapi terkait: penyelarasan data dan struktur data padding . Ketika komputer modern membaca dari atau menulis ke alamat memori, itu akan melakukan ini dalam potongan berukuran kata (misalnya potongan 4 byte pada sistem 32-bit) atau lebih besar. Penyelarasan data berarti menempatkan data pada alamat memori sama dengan beberapa kelipatan dari ukuran kata, yang meningkatkan kinerja sistem karena cara CPU menangani memori. Untuk menyelaraskan data, mungkin perlu untuk menyisipkan beberapa byte yang tidak berarti antara akhir struktur data terakhir dan awal berikutnya, yaitu padding struktur data.
sumber