Mengapa mendeklarasikan struct yang hanya berisi array di C?

131

Saya menemukan beberapa kode yang mengandung yang berikut:

struct ABC {
    unsigned long array[MAX];
} abc;

Kapan masuk akal untuk menggunakan deklarasi seperti ini?

Joe.Z
sumber

Jawaban:

184

Ini memungkinkan Anda untuk melewatkan array ke suatu fungsi dengan nilai, atau mendapatkannya kembali dengan nilai dari suatu fungsi.

Struct dapat diteruskan oleh nilai, tidak seperti array yang membusuk ke pointer dalam konteks ini.

Buyuciev Blagovest
sumber
1
Hati-hati melakukan ini dengan array, lebih dari mengatakan 16 atau 32 byte, untuk fungsi yang tidak sesuai: lebih efisien untuk meneruskannya dengan referensi-const, kecuali callee sudah membutuhkan salinan tmp yang dapat dihancurkan. Jika panggilan / kembali tidak dioptimalkan, array menengah ke besar (ribuan byte) adalah hal yang buruk untuk dilewati oleh nilai.
Peter Cordes
85

Keuntungan lainnya adalah ia mengabstraksi ukurannya sehingga Anda tidak perlu menggunakan [MAX]seluruh kode Anda di mana pun Anda mendeklarasikan objek semacam itu. Ini juga bisa dicapai dengan

typedef char ABC[MAX];

tetapi kemudian Anda memiliki masalah yang jauh lebih besar: Anda harus sadar akan hal itu ABC adalah tipe array (walaupun Anda tidak dapat melihat ini ketika Anda mendeklarasikan variabel tipe ABC) atau Anda akan tersengat oleh fakta bahwa itu ABCakan berarti sesuatu yang berbeda dalam daftar argumen fungsi versus dalam deklarasi / definisi variabel.

Satu lagi keuntungan adalah bahwa struct memungkinkan Anda untuk menambahkan lebih banyak elemen jika perlu, tanpa harus menulis ulang banyak kode.

R .. GitHub BERHENTI MEMBANTU ICE
sumber
45

Anda bisa menyalin struct dan mengembalikan struct dari suatu fungsi.

Anda tidak dapat melakukannya dengan array - kecuali jika itu adalah bagian dari struct!

Bo Persson
sumber
26

Anda bisa menyalinnya seperti ini.

struct ABC a, b;
........
a = b;

Untuk sebuah array, Anda perlu menggunakan fungsi memcpy atau loop untuk menetapkan setiap elemen.

MetallicPriest
sumber
6
(sehingga memungkinkan kode pembersih - tidak akan membuat perbedaan dalam kecepatan dll)
John Carter
3
Itu berguna. Sayangnya Anda tidak dapat melakukannya jika (a == b)!?! betapa tidak konsistennya itu. Untuk C ++ ia mencari operator ==. Di C tertulis "operan tidak valid ke biner ==".
Mat
11

Anda bisa menggunakan struct untuk membuat tipe data baru seperti string . Anda dapat mendefinisikan:

struct String {
    char Char[MAX];
};

atau Anda bisa membuat daftar data yang bisa Anda gunakan dengan argumen fungsi atau mengembalikannya dalam metode Anda. Struct lebih fleksibel daripada array, karena dapat mendukung beberapa operator seperti = dan Anda dapat mendefinisikan beberapa metode di dalamnya.

Semoga bermanfaat buat kamu :)

Hossein Mobasher
sumber
2
Pada dasarnya, ini adalah hal terdekat yang harus dimiliki C untuk menciptakan sebuah kelas. Saya suka jawaban ini karena itu yang paling dekat dengan menunjukkan itu.
Nate CK
1
Tidak ada yang namanya metode dalam C. structs di C adalah data lama. Ini memiliki = operator yang didukung secara default (yang jawaban lain tunjukkan adalah alasan untuk melakukan ini), tetapi ini menyesatkan dan sebagian besar berlaku untuk C ++, bukan C.
Jonathan Sternberg
3
@J Sternberg: "Metode" hanyalah cara berpikir tentang subrutin yang terkait dengan "objek" data yang mereka pengaruhi. Anda tentu dapat membuat "kelas" dari "objek" dan "metode" yang beroperasi pada mereka dalam C. Bahasa tidak secara formal mendefinisikan hal-hal seperti itu. Jika Anda ingin membuat abstraksi yang lebih baik dalam C, memasukkan hal-hal ke dalam struct biasanya merupakan cara terbaik untuk melakukannya.
Nate CK
Selain itu, jika Anda benar-benar ingin "membuat" metode dalam C, Anda bisa menggunakan pointer fungsi (ya, ya, sintaks yang rumit, tidak ada perlindungan data, dll) untuk mengaitkan fungsi dengan data yang mereka operasikan. Anda harus memasukkan "diri" dalam argumen pertama (Anda bahkan bisa menamainya "ini", jika Anda mau), karena tidak ada penciptaan otomatis dari pointer ini di dalam fungsi dalam C. Tentu saja, itu semua senam, Anda dapat hal-hal seperti ini secara default di C ++, meskipun memang benar mungkin ada overhead tersembunyi sebagai bonus ...
BenPen
2

Keuntungan lain menggunakan a seperti itu structadalah memberlakukan keamanan jenis di mana pun seperti structitu digunakan; terutama jika Anda memiliki dua tipe yang terdiri dari array dengan ukuran yang sama yang digunakan untuk tujuan yang berbeda, tipe-tipe ini akan membantu Anda menghindari penggunaan array secara tidak sengaja.

Jika Anda tidak membungkus array dalam struct, Anda masih dapat mendeklarasikannya typedef: ini memiliki beberapa kelebihan dari struct- • jenisnya dideklarasikan sekali, • ukurannya secara otomatis benar, • maksud kode menjadi lebih jelas, • dan kode lebih mudah dikelola - tetapi Anda kehilangan ◦ keamanan jenis yang ketat, ◦ kemampuan untuk menyalin dan mengembalikan nilai jenis dan ◦ kemampuan untuk menambah anggota nanti tanpa merusak sisa kode Anda. Dua typedefs untuk array kosong dari tipe yang diberikan hanya menghasilkan tipe yang berbeda jika ukurannya berbeda. Selain itu, jika Anda menggunakan typedeftanpa *dalam argumen fungsi, itu setara dengan char *, secara drastis mengurangi keamanan tipe.

Singkatnya :

typedef struct A_s_s { char m[113]; } A_s_t; // Full type safey, assignable
typedef char   A_c_t[113];                   // Partial type-safety, not assignable

A_s_t          v_s(void);     // Allowed
A_c_t          v_c(void);     // Forbidden

void           s__v(A_s_t);     // Type-safe, pass by value
void           sP_v(A_s_t *);   // Type-safe
void           c__v(A_c_t);     // UNSAFE, just means char * (GRRR!)
void           cP_v(A_c_t *);   // SEMI-safe, accepts any array of 113
PJTraill
sumber
1

Struktur dapat berisi inisialisasi array, fungsi copy dan fini meniru beberapa keuntungan dari paradigma manajemen memori OOP. Bahkan, sangat mudah untuk memperluas konsep ini untuk menulis utilitas manajemen memori generik (dengan menggunakan sizeof () struktur untuk mengetahui dengan tepat berapa banyak byte yang dikelola) untuk mengelola struktur yang ditentukan pengguna. Banyak basis kode produksi pintar yang ditulis dalam C banyak menggunakan ini dan biasanya tidak pernah menggunakan array kecuali ruang lingkupnya sangat lokal.

Bahkan untuk array yang tertanam dalam struktur, Anda bisa melakukan "hal-hal pintar" lainnya seperti memeriksa kapan saja Anda ingin mengakses array ini. Sekali lagi, kecuali ruang lingkup array sangat terbatas, itu ide yang buruk untuk menggunakannya dan menyebarkan informasi di seluruh program. Cepat atau lambat, Anda akan menemukan bug yang membuat Anda tetap terjaga di malam hari dan merusak akhir pekan Anda.

Aniket
sumber
Ini tidak menjawab pertanyaan mengapa orang mungkin menggunakan hanya array yang structmengandung .
PJTraill