I've hanya datang atas lagi kode dasar di tempat kerja dimana pengusaha secara konsisten menggunakan alamat dari elemen pertama dari struct ketika menyalin/membandingkan/pengaturan, daripada struct itu sendiri. Berikut ini's contoh sederhana.
Pertama ada's struct jenis:
typedef struct {
int a;
int b;
} foo_t;
Kemudian ada's sebuah fungsi untuk membuat salinan dari sebuah struct:
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
Saya tidak't diriku menulis panggilan untuk memcpy
dengan cara itu dan aku mulai dengan mencurigai bahwa pengembang hanya didn't cukup memahami petunjuk dan struct dalam bahasa C. Namun, sekarang saya've melihat ini dalam dua terkait kode basa, dengan tidak umum pengembang jadi saya'm mulai meragukan diri saya sendiri.
Mengapa seseorang ingin menggunakan gaya ini?
Bukan itu:
memcpy(&l.a, &inp->a, sizeof(foo_t));
anda dapat melakukannya:
memcpy(&l, inp, sizeof(foo_t));
Sementara itu dapat menjadi berbahaya dan menyesatkan, kedua pernyataan benar-benar melakukan hal yang sama di sini seperti C menjamin tidak ada padding sebelum pertama struktur anggota.
Tapi yang terbaik adalah hanya untuk menyalin struktur benda-benda yang sederhana dengan menggunakan operator penugasan:
l = *inp;
Mengapa anda ingin menggunakan gaya ini?
Saya kira: ketidaktahuan atau buruk disiplin.
Kode ini tidak aman karena menata ulang anggota struct dapat mengakibatkan memcpy
mengakses di luar batas struct jika anggota a
adalah tidak ada lagi anggota pertama.
Namun, hal's dibayangkan bahwa anggota yang sengaja diperintahkan dalam struct dan programmer hanya ingin copy sebagian dari mereka, awal dengan anggota a
dan berjalan sampai akhir struct. Jika itu's terjadi maka kode dapat dibuat aman dengan perubahan berikut:
memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
Sekarang struct anggota dapat disusun kembali ke dalam urutan apapun dan ini memcpy
tidak akan pernah pergi keluar dari batas.
It's benar-benar kebiasaan buruk. Struct mungkin anggota lain ditambahkan, misalnya. Ini adalah aplikasi yang gila-gilaan ceroboh kebiasaan dan saya terkejut untuk membaca yang siapa pun akan melakukan hal ini.
Lain-lain telah mencatat ini; salah satu yang mengganggu saya adalah ini:
struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];
bukan
struct Foo *pfoo = rgfoo;
Mengapa deref array dengan indeks dan kemudian mengambil alamat lagi? It's sudah alamat, satu-satunya perbedaan dari catatan adalah bahwa pfoo teknis
struct Foo *const,
tidak
struct Foo *.
Namun saya digunakan untuk melihat yang pertama sepanjang waktu.
Sebenarnya, ada satu penggunaan yang sah untuk kasus ini: membangun hirarki kelas.
Ketika mengobati struct sebagai kelas turunan, anggota pertama (yaitu offset 0) biasanya akan menjadi supertipe contoh... jika supertipe ada. Hal ini memungkinkan cor sederhana untuk beralih antara menggunakan subtipe vs supertype. Sangat berguna.
Pada Darren Batu's catatan tentang niat, ini adalah diharapkan ketika menjalankan OO dalam bahasa C.
In lain case, saya akan menyarankan menghindari pola ini dan mengakses anggota secara langsung, bukan, untuk alasan yang sudah dikutip.