Mengapa struktur yang dikemas bukan bagian dari bahasa C?

10

Setiap kompiler C menawarkan opsi untuk "mengemas" struktur C (misalnya __attribute__ ((__packed__)), atau #pragma pack()). Sekarang, kita semua tahu bahwa pengemasan diperlukan, jika kita ingin mengirim atau menyimpan data dengan cara yang andal. Ini juga harus menjadi persyaratan sejak hari pertama bahasa C.

Jadi saya bertanya-tanya mengapa struktur yang dikemas bukan bagian dari spesifikasi bahasa C? Mereka bahkan tidak di C99 atau C11 meskipun keharusan memiliki mereka dikenal selama beberapa dekade sekarang? Apa yang saya lewatkan? Mengapa ini khusus untuk kompiler?

grasbueschel
sumber
2
Mereka tidak perlu menulis kode C murni.
user253751

Jawaban:

7

Saya kira itu karena itu tergantung pada kombinasi target CPU / compiler yang digunakan. Ini berarti bahwa lebih baik menjadi arahan kompiler (karena ini terkait dengan itu) daripada aspek bahasa, karena bagaimana menentukannya? Satu-satunya cara mereka bisa melakukannya adalah dengan persatuan.

Artikel Raymond memberikan beberapa wawasan mengapa ini adalah: http://www.catb.org/esr/structure-packing/

Frans Bouma
sumber
Artikel yang sangat menarik. (+1)
Giorgio
Kesulitan apa yang ada dalam mengizinkan kode untuk mengatakan "Saya memerlukan struktur yang menyimpan 12 byte; bidang X harus berperilaku sebagai bilangan bulat 32-bit yang disimpan sebagai empat oktet little-endian pada offset 0; bidang Y harus berperilaku sebagai bilangan bulat 64-bit disimpan sebagai octet bytes little-endian di offset 4 "? Kode untuk mengatasinya pada platform apa pun seharusnya tidak lebih buruk daripada yang harus dimiliki oleh kompiler untuk bitfields, dan dalam kasus di mana programmer dapat menentukan keselarasan yang cocok dengan mesin asli bisa jauh lebih efisien. Pada mesin lain, itu akan menjadi kurang efisien tetapi masih portabel.
supercat
5

Ada tiga faktor utama.

  1. Beberapa prosesor tidak dapat mengakses data yang tidak selaras (misalnya integer atau float mulai dari alamat ganjil). Mencoba melakukan memicu pengecualian.
  2. Beberapa prosesor dapat mengakses data yang tidak selaras, tetapi dengan biaya kinerja.
  3. Sebagian besar struktur diakses oleh satu set kode sumber C / C ++, dan interoperabilitas dengan bahasa lain adalah pengecualian, bukan aturannya.

Dengan mempertimbangkan faktor-faktor ini, standar dan semua kompiler C / C ++ secara rutin membuat struktur pad untuk memastikan keselarasan optimal untuk prosesor, tetapi juga menyediakan mekanisme untuk menimpanya jika diperlukan untuk keperluan interop.

Ini sama sekali bukan sesuatu yang telah diabaikan. Ini sangat dipahami dengan baik dan situasi saat ini adalah dengan desain. Versi terbaru dari standar C ++ memiliki dukungan luas untuk menangani masalah penyelarasan, yang mungkin tidak Anda kenal.

david.pfx
sumber
Argumen apa pun yang dapat dibuat terhadap struktur yang dikemas juga dapat digunakan untuk membenarkan menjadikan bitfield sebagai fitur opsional. Mengakses anggota dari struktur yang dikemas akan lambat pada beberapa prosesor, cepat pada yang lain, tetapi memiliki kompiler mencoba untuk mengganti solusi kode pengguna karena kurangnya fitur akses yang tidak selaras dengan kode yang lebih efisien adalah jauh lebih rumit daripada hanya memiliki kompiler membiarkan programmer menentukan apa mereka butuh.
supercat
@supercat: apa yang Anda perdebatkan (atau lawan)? Saya tidak mengerti.
david.pfx
Saya berpendapat bahwa bitfields harus opsional, tetapi jika bitfields akan menjadi fitur wajib maka masuk akal untuk memperluasnya dengan cara yang memungkinkan kontrol eksplisit tata letak struct. Jika tidak, efek bersihnya adalah bahwa kompiler harus melakukan 90% dari pekerjaan yang akan diperlukan untuk kontrol tata letak penuh, tetapi programmer hanya memetik 10% dari manfaatnya.
supercat
@supercat: bidang-bit adalah bilangan bulat dan ikuti aturan tata letak bit yang sama dengan bilangan bulat: implementasi didefinisikan. Anggota Struct diperintahkan pada batas karakter seperti yang dinyatakan, mungkin dengan kemasan dimasukkan. Mereka secara konseptual cukup terpisah. [Anda harus mengajukan pertanyaan lain jika ingin memperluas proposal Anda, tetapi saya rasa itu tidak akan berhasil sama sekali.]
david.pfx
0

Ini adalah compiler-spesifik karena tidak dalam standar. Dan itu tidak dalam standar karena akan sulit untuk menentukan dengan cara yang tidak akan membutuhkan banyak upaya implementasi untuk kompiler dari platform yang tidak jelas dengan pembatasan penyelarasan yang dipaksakan.

Dan tidak ada upaya yang memiliki banyak pembenaran, karena setiap kompiler / platform yang digunakan oleh siapa pun yang menggunakan kompiler C89 atau yang lebih baru sudah menerapkannya.

soru
sumber
2
??? Anda menjawab pertanyaan "Mengapa tidak dalam bahasa standar" dengan mengatakan "karena tidak ada dalam standar" ...
Emilio Garavaglia
Itulah yang saya pikirkan pertama, tetapi sekali lagi, orang dapat menentukan fitur seperti "jika struct didefinisikan dengan kata kunci 'dikemas' ukurannya dijamin sama dengan ukuran tambahan dari setiap anggota individu. Pada platform yang tidak mendukung akses memori yang tidak selaras, akses ke salah satu nilai anggota struct adalah perilaku yang tidak terdefinisi. " Ini akan memungkinkan pengembang di platform tanpa akses yang tidak selaras untuk setidaknya mengetahui ukuran struct dan offset masing-masing anggota ...
grasbueschel
1
Adalah mungkin untuk membuat akses yang tidak selaras bekerja pada sistem yang tidak mendukungnya dalam perangkat keras dengan mengimplementasikan struct seperti array byte dan melakukan bit-shifting dan &/ |operasi yang diperlukan untuk membaca / menulis nilai-nilai setiap bidang.
dan04
1
@ dan04: Pada banyak prosesor, kompiler dapat menghasilkan kode untuk akses yang tidak selaras yang lebih efisien daripada menggunakan urutan byte reads and shifts. Memiliki sintaks untuk itu akan membuatnya lebih mudah untuk kompiler seperti itu untuk menghasilkan kode yang efisien daripada mengharuskan mereka untuk mengenali semua cara yang berbeda programmer dapat mencoba menulis kode untuk merakit byte menjadi tipe yang lebih panjang.
supercat