Saya telah mendefinisikan struktur ini.

struct http_req {
    struct http_req_line rl;
}

struct http_req_line {
    enum method {
        OPTIONS,
        GET,
        HEAD,
        POST,
        PUT,
        DELETE,
        TRACE,
        CONNECT
    } method;
    enum uri_type {
        ASTERISK,
        ABSOLUTEURI,
        ABS_PATH,
        AUTHORITY
    } uri_type;
    union req_uri {
        char asterisk[1];
        char absoluteURI[256];
        char abs_path[256];
        char authority[256];
    } req_uri;
    char http_ver[16];
};

Ketika saya mengkompilasi file, file header ini disertakan (yang mengkompilasi dengan baik sendiri), gcc memberi saya ini

request_types.h:2:23: error: field ‘rl’ has incomplete type
  struct http_req_line rl;

Tapi mengubah baris ke-2 dari header menjadi

struct http_req_line *rl;

Menghilangkan kesalahan ini. Apa yang menyebabkan kesalahan ini, dan apakah mengubah anggota itu menjadi penunjuk benar-benar memperbaiki masalah, atau hanya menyembunyikannya dari kompiler?

0
pictureman123 4 Januari 2021, 17:48

3 jawaban

Jawaban Terbaik

Pada titik di mana kompiler melihat:

struct http_req {
    struct http_req_line rl;
}

Tidak ada informasi tentang apa itu struct http_req_line. Anda memerlukan definisi struktur agar struct http_req muncul setelah definisi struct http_req_line. Anda dapat menggunakan pointer (ke tipe yang tidak lengkap); Anda tidak dapat menggunakan salinan struktur.

Lihat §6.7.2.1 Struktur dan union specifier standar C11 :

Struktur atau serikat pekerja tidak boleh berisi anggota dengan tipe fungsi atau tidak lengkap (oleh karena itu, struktur tidak boleh berisi turunan dari dirinya sendiri, tetapi dapat berisi penunjuk ke turunannya sendiri), …

5
Jonathan Leffler 4 Januari 2021, 14:54

Anda melihat kesalahan ini karena Anda mencoba untuk mendefinisikan sebuah instance dari sebuah struct sebelum struct itu sendiri telah didefinisikan. Anda perlu mendefinisikannya terlebih dahulu, lalu menggunakannya:

struct http_req_line {
    enum method {
        OPTIONS,
        GET,
        HEAD,
        POST,
        PUT,
        DELETE,
        TRACE,
        CONNECT
    } method;
    enum uri_type {
        ASTERISK,
        ABSOLUTEURI,
        ABS_PATH,
        AUTHORITY
    } uri_type;
    union req_uri {
        char asterisk[1];
        char absoluteURI[256];
        char abs_path[256];
        char authority[256];
    } req_uri;
    char http_ver[16];
};


struct http_req {
    struct http_req_line rl;
};

Alasan mengapa mengubah tipe anggota menjadi pointer berfungsi adalah karena Anda tidak perlu memiliki definisi struct lengkap untuk menggunakan pointer ke sana. Ketika definisi tipe adalah yang dibutuhkan adalah saat pointer itu akan di-dereferensi.

4
dbush 4 Januari 2021, 14:55

Pada titik di mana Anda mendefinisikan struct http_req, struct http_req_line tidak diketahui. Kompilator tidak mengetahui seberapa besar atau apa persyaratan keselarasannya, sehingga tidak tahu berapa banyak ruang yang digunakan untuk anggota rl dan tidak dapat menyelesaikan definisi struct http_req.

Jika Anda ingin menyematkan struct http_req_line di dalam struct http_req, pindahkan definisi struct http_req_line sebelum definisi struct http_req.

Jika Anda mengubah rl menjadi pointer, tipenya tidak lengkap dalam arti C karena kompiler akan tahu seberapa besar pointer dan apa persyaratan penyelarasannya. Tidak perlu mengetahui seberapa besar struktur yang ditunjuknya untuk dapat merencanakan ruang untuk pointer rl.

4
Eric Postpischil 4 Januari 2021, 14:54