Bagaimana Anda membandingkan dua contoh struct untuk kesetaraan dalam standar C?
216
C tidak menyediakan fasilitas bahasa untuk melakukan ini - Anda harus melakukannya sendiri dan membandingkan setiap anggota struktur dengan anggota.
0.0, -0.0 NaN
masalahmemcmp()
. Pointer yang berbeda dalam representasi biner dapat menunjuk ke lokasi yang sama (misalnya DOS: seg: offset) dan sama. Beberapa sistem memiliki beberapa pointer nol yang membandingkan secara merata. Sama untuk yang tidak jelasint
dengan -0 dan tipe floating point dengan pengkodean redundan. (Intel long double, decimal64, dll.) Masalah-masalah ini tidak membuat perbedaancalloc()
digunakan atau tidak atau padding.==
tidak bekerja dengan struktur (seperti saya), silakan lihat stackoverflow.com/questions/46995631/…Anda mungkin tergoda untuk menggunakannya
memcmp(&a, &b, sizeof(struct foo))
, tetapi mungkin tidak berfungsi dalam semua situasi. Kompiler dapat menambahkan ruang penyejajaran penyelarasan ke struktur, dan nilai-nilai yang ditemukan di lokasi memori yang terletak di ruang buffer tidak dijamin menjadi nilai tertentu.Tetapi, jika Anda menggunakan
calloc
ataumemset
ukuran penuh dari struktur sebelum menggunakannya, Anda dapat melakukan perbandingan yang dangkalmemcmp
(jika struktur Anda berisi pointer, itu hanya akan cocok jika alamat yang ditunjuk pointer adalah sama).sumber
memcmp
asalkan memori telah dihapus terlebih dahulu. Yang dekat dengan bekerja tetapi tidak benar. Ofc pertanyaannya juga tidak mendefinisikan "kesetaraan", jadi jika Anda menganggapnya "kesetaraan byte-bijaksana dari representasi objek" kemudianmemcmp
melakukan hal itu (apakah memori dihapus atau tidak).Jika Anda sering melakukannya saya sarankan menulis fungsi yang membandingkan dua struktur. Dengan begitu, jika Anda pernah mengubah struktur, Anda hanya perlu mengubah perbandingan di satu tempat.
Adapun cara melakukannya .... Anda harus membandingkan setiap elemen secara individual
sumber
Anda tidak dapat menggunakan memcmp untuk membandingkan struct untuk kesetaraan karena potensi karakter padding acak antara bidang dalam struct.
Di atas akan gagal untuk struct seperti ini:
Anda harus menggunakan perbandingan anggota-bijaksana agar aman.
sumber
@Reg benar bahwa seseorang harus menulis fungsi perbandingan eksplisit dalam kasus umum.
Dimungkinkan untuk digunakan
memcmp
jika:NaN
.-Wpadded
dengan dentang untuk memeriksa ini) ATAU struct secara eksplisit diinisialisasi denganmemset
saat inisialisasi.BOOL
) yang memiliki nilai berbeda tetapi setara.Kecuali Anda pemrograman untuk embedded system (atau menulis perpustakaan yang mungkin digunakan pada mereka), saya tidak akan khawatir tentang beberapa kasus sudut dalam standar C. Perbedaan pointer dekat vs jauh tidak ada pada perangkat 32- atau 64-bit. Tidak ada sistem non-embedded yang saya tahu memiliki banyak
NULL
pointer.Pilihan lain adalah untuk menghasilkan fungsi kesetaraan secara otomatis. Jika Anda meletakkan definisi struct Anda dengan cara yang sederhana, dimungkinkan untuk menggunakan pemrosesan teks sederhana untuk menangani definisi struct yang sederhana. Anda dapat menggunakan libclang untuk case umum - karena menggunakan frontend yang sama dengan Clang, ia menangani semua case sudut dengan benar (bug pembatas).
Saya belum melihat perpustakaan pembuatan kode seperti itu. Namun, tampaknya relatif sederhana.
Namun, ini juga merupakan kasus dimana fungsi kesetaraan yang dihasilkan seperti itu sering melakukan hal yang salah pada level aplikasi. Misalnya, haruskah dua
UNICODE_STRING
struct di Windows dibandingkan secara dangkal atau dalam?sumber
memset
, dll. Tidak menjamin nilai bit padding setelah menulis lebih lanjut ke elemen struct, lihat: stackoverflow.com/q/52684192/689161Catatan Anda dapat menggunakan memcmp () pada struktur yang tidak statis tanpa khawatir tentang bantalan, selama Anda tidak menginisialisasi semua anggota (sekaligus). Ini didefinisikan oleh C90:
http://www.pixelbeat.org/programming/gcc/auto_init.html
sumber
{0, }
juga akan nol byte padding?Itu tergantung pada apakah pertanyaan yang Anda ajukan adalah:
Untuk mengetahui apakah mereka adalah objek yang sama, bandingkan pointer ke dua struct untuk kesetaraan. Jika Anda ingin mencari tahu secara umum jika mereka memiliki nilai yang sama Anda harus melakukan perbandingan yang mendalam. Ini melibatkan membandingkan semua anggota. Jika anggotanya adalah penunjuk ke struct lain Anda juga perlu recurse ke struct tersebut juga.
Dalam kasus khusus di mana struct tidak mengandung pointer, Anda dapat melakukan memcmp untuk melakukan perbandingan bitwise dari data yang terkandung dalam masing-masing tanpa harus tahu apa artinya data.
Pastikan Anda tahu apa arti 'sama dengan' untuk setiap anggota - jelas untuk int tetapi lebih halus ketika datang ke nilai floating-point atau tipe yang ditentukan pengguna.
sumber
memcmp
tidak membandingkan struktur,memcmp
membandingkan biner, dan selalu ada sampah di struct, oleh karena itu selalu keluar Palsu sebagai perbandingan.Bandingkan elemen demi elemen yang aman dan tidak gagal.
sumber
Jika struct hanya berisi primitif atau jika Anda tertarik pada kesetaraan yang ketat maka Anda dapat melakukan sesuatu seperti ini:
Namun, jika struct Anda berisi pointer ke struct atau serikat lain maka Anda harus menulis fungsi yang membandingkan primitif dengan benar dan membuat panggilan perbandingan terhadap struktur lain yang sesuai.
Perlu diketahui, bahwa Anda harus menggunakan memset (& a, sizeof (struct my_struct), 1) untuk nol rentang memori struktur sebagai bagian dari inisialisasi ADT Anda.
sumber
jika variabel 2 struktur diinisialisasi dengan calloc atau mereka diatur dengan 0 oleh memset sehingga Anda dapat membandingkan 2 struktur Anda dengan memcmp dan tidak ada kekhawatiran tentang struktur sampah dan ini akan memungkinkan Anda untuk mendapatkan waktu
sumber
Contoh patuh ini menggunakan ekstensi kompilator paket #pragma dari Microsoft Visual Studio untuk memastikan anggota struktur dikemas sekencang mungkin:
sumber