Saya sudah lama tidak menulis C, jadi saya tidak yakin bagaimana saya harus melakukan hal-hal rekursif semacam ini ... Saya ingin setiap sel mengandung sel lain, tetapi saya mendapatkan kesalahan di sepanjang baris "bidang 'anak' memiliki tipe tidak lengkap". Ada apa?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
Jawaban:
Jelas suatu sel tidak dapat mengandung sel lain karena ia menjadi rekursi yang tidak pernah berakhir.
Namun sebuah sel BISA berisi pointer ke sel lain.
sumber
Cell
belum dalam cakupan.Cell*
kecell->child
.struct
s di C pada dasarnya hanya menyimpan semua nilai mereka di samping satu sama lain, tidak mungkin untuk benar-benar menyimpan struct itu sendiri (karena struct itu harus mengandung yang lain dan seterusnya, yang mengarah ke struktur memori ukuran tak terbatas) .struct Cell
, lihat jawaban ini .Di C, Anda tidak bisa mereferensikan typedef yang Anda buat dengan struktur itu sendiri. Anda harus menggunakan nama struktur, seperti dalam program pengujian berikut:
Meskipun mungkin jauh lebih rumit daripada ini dalam standar, Anda dapat menganggapnya sebagai kompiler yang mengetahui tentang
struct Cell
baris pertamatypedef
tetapi tidak tahu tentangtCell
sampai baris terakhir :-) Begitulah cara saya mengingat aturan itu.sumber
Dari sudut pandang teoretis, Bahasa hanya dapat mendukung struktur referensi-diri bukan struktur inklusif.
sumber
Ada beberapa cara untuk mengatasi hal ini:
Jika Anda mendeklarasikannya seperti ini, ia dengan benar mengatakan kepada kompiler bahwa struct Cell dan plain-ol'-cell adalah sama. Jadi Anda bisa menggunakan Cell seperti biasa. Masih harus menggunakan struct Cell di dalam deklarasi awal itu sendiri.
sumber
struct Cell;
lagi?struct Cell
.struct Cell;
berlebihan. Namun, jika karena alasan tertentu Anda memasukkan dua baris terakhir ke dalam file header yang Anda sertakan sebelum Anda mendefinisikanCell
struct dengan empat baris pertama, maka tambahannyastruct Cell;
adalah nececairy.typedef struct Cell Cell;
dan itu akan membuatCell
alias untukstruct Cell
. Tidak masalah apakah kompiler telah melihatstruct Cell { .... }
sebelumnya.Saya tahu posting ini sudah tua, namun, untuk mendapatkan efek yang Anda cari, Anda mungkin ingin mencoba yang berikut:
Dalam salah satu dari dua kasus yang disebutkan dalam fragmen kode di atas, Anda HARUS mendeklarasikan struktur sel anak Anda sebagai pointer. Jika tidak, maka Anda akan mendapatkan kesalahan "bidang 'anak' memiliki tipe tidak lengkap". Alasannya adalah bahwa "struct Cell" harus didefinisikan agar kompiler mengetahui berapa banyak ruang yang dialokasikan ketika digunakan.
Jika Anda mencoba menggunakan "struct Cell" di dalam definisi "struct Cell", maka kompiler belum dapat mengetahui berapa banyak ruang yang harus diambil oleh "struct Cell". Namun, kompiler sudah tahu berapa banyak ruang yang dibutuhkan pointer, dan (dengan deklarasi maju) ia tahu bahwa "Sel" adalah jenis "sel struct" (walaupun belum tahu seberapa besar "sel Cell" adalah ). Jadi, kompiler dapat mendefinisikan "Sel *" di dalam struct yang sedang didefinisikan.
sumber
Mari kita pergi melalui definisi dasar typedef. typedef digunakan untuk mendefinisikan alias ke tipe data yang ada baik itu yang ditentukan pengguna atau bawaan.
sebagai contoh
Kebingungan di sini adalah dengan struktur referensial diri, karena anggota dengan tipe data yang sama yang tidak didefinisikan sebelumnya. Jadi Dengan cara standar Anda dapat menulis kode Anda sebagai: -
Tetapi opsi terakhir menambah beberapa baris dan kata-kata tambahan dengan biasanya kita tidak ingin melakukan (kita sangat malas lho;)). Jadi lebih suka View 2.
sumber
typedef
sintaksis salah (pertimbangkan misalnyatypedef int (*foo)(void);
). Contoh Lihat 1 dan 2 Lihat Anda tidak berfungsi: Mereka membuatstruct Cell
jenis yang tidak lengkap, sehingga Anda tidak dapat benar-benar menggunakannyachild
dalam kode Anda.Metode lain yang mudah adalah dengan pra-mengetikkan struktur dengan, tag struktur sebagai:
sumber
Struktur yang berisi referensi ke dirinya sendiri. Kejadian umum ini dalam struktur yang menggambarkan node untuk daftar tautan. Setiap node membutuhkan referensi ke node berikutnya dalam rantai.
sumber
Semua jawaban sebelumnya bagus, saya hanya berpikir untuk memberikan wawasan tentang mengapa suatu struktur tidak dapat memuat turunan dari jenisnya sendiri (bukan referensi).
itu sangat penting untuk dicatat bahwa struktur adalah tipe 'nilai' yaitu mengandung nilai aktual, jadi ketika Anda mendeklarasikan struktur, kompiler harus memutuskan berapa banyak memori yang dialokasikan untuk sebuah instance, sehingga ia akan melewati semua anggotanya dan menambahkan memori mereka untuk mencari tahu seluruh memori struct, tetapi jika kompilator menemukan sebuah instance dari struct yang sama di dalam maka ini adalah sebuah paradoks (yaitu untuk mengetahui berapa banyak memori struct A yang dibutuhkan Anda harus memutuskan berapa banyak memori struct A mengambil!).
Tetapi tipe referensi berbeda, jika struct 'A' berisi 'referensi' ke instance dari jenisnya sendiri, meskipun kita belum tahu berapa banyak memori yang dialokasikan untuk itu, kita tahu berapa banyak memori dialokasikan ke memori alamat (yaitu referensi).
HTH
sumber