Apa perlunya kawat gigi kosong '{}' di akhir array struct?

59

Saya menekan beberapa kode di kernel Linux:

static struct ctl_table ip_ct_sysctl_table[] = {
    {
        .procname   = "ip_conntrack_max",
        .maxlen     = sizeof(int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec,
    },
    // ...
    {
        .procname   = "ip_conntrack_log_invalid",
        .maxlen     = sizeof(unsigned int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec_minmax,
        .extra1     = &log_invalid_proto_min,
        .extra2     = &log_invalid_proto_max,
    },
    { }
};

Di sini array struct berakhir dengan { }. Untuk tujuan apa ditambahkan?
By the way, sedikit di atas kode ini ada array struct lain , tetapi tanpa kawat gigi kosong di akhir.

Kapan saya harus menggunakan kawat gigi kosong di akhir array struct?

Sel NK
sumber
1
Hmm bagaimana jika itu ditambahkan ke sinyal akhir array seperti 0 sinyal akhir string? Hanya menebak.
Eraklon
4
Ini adalah beberapa ekstensi GCC non-standar. Dan dengan demikian, sangat mungkin datang dengan sedikit atau tanpa dokumentasi ... Saya baru saja membaca semua dokumen dan saya tidak dapat menemukan apa pun tentang daftar initializer struct kosong. Namun ia mengkompilasi, kecuali Anda memaksakan ISO ketat dengan -pedantic.
Lundin
9
Lagi pula, ini adalah nilai "sentinel", sebuah item dengan semuanya diatur ke nol / NULL untuk menandai akhir array.
Lundin
Sentinel juga umum dalam modul ekstensi CPython .
MaxPowers

Jawaban:

38

Perubahan khusus ini adalah bagian dari jaring sysctl: Hapus kode sysctl biner yang tidak digunakan yang dilakukan oleh Eric W. Biederman, mengubah inisialisasi elemen terakhir ip_ct_sysctl_tablearray dari {0}menjadi {}(dan melakukan perubahan yang mirip dengan banyak inisialisasi array lainnya).

The {0}pola tampaknya telah sekitar untuk lebih lama lagi meskipun, dan kedua {0}atau {}akhir elemen-inisialisasi umumnya (dalam kode sumber Linux) secara eksplisit disebut sebagai Terminating entry, sehingga kemungkinan hadiah pola untuk memungkinkan mengkonsumsi array ini tanpa mengetahui panjang mereka, mengakhiri konsumsi saat menekan entri terminasi yang diinisialisasi nol. Misalnya untuk array yang sama dalam sound/aoa/fabrics/snd-aoa-fabric-layout.cmaksud inisialisasi nol bahkan secara eksplisit disebutkan dalam komentar, misalnya:

static struct codec_connection toonie_connections[] = {
  {
      .connected = CC_SPEAKERS | CC_HEADPHONE,
      .codec_bit = 0,
  },
  {} /* terminate array by .connected == 0 */
};
dfri
sumber
11
Akan menarik untuk mengetahui alasan mereka untuk menjatuhkan standar C mendukung ekstensi GCC yang 100% setara dalam hal fungsionalitas. Semua yang dilakukannya adalah mencegah kode dari kompilasi pada kompiler standar C Artinya, seharusnya setara 100% karena gcc tampaknya tidak mendokumentasikan fitur ini ... Ini bukan array panjang nol, ini adalah daftar penginisialisasi kosong.
Lundin
@Lundin Tidak akan int arr[] = {}(mengingat bahwa kita menggunakan ekstensi initializer kosong GNU) menghasilkan array kosong; yaitu, ukuran arrmakhluk 0?
dfri
1
@Lundin: Halaman cppreference bertentangan dengan kata-kata ISO / IEC 9899: 2011, yang memungkinkan untuk itu (§6.7.9 (21)). Tidak ada inisialisasi yang tidak diragukan "lebih sedikit" dari anggota agregat. Jadi itu bukan ekstensi kompiler yang aneh, tetapi C. yang sah
Damon
2
@ Damon Ini tidak valid C dan itu terkenal ... kompilasi dengan gcc -pedantic-errors. Untuk memahami alasannya, Anda perlu membaca sintaks aktual untuk daftar penginisialisasi, di atas 6.7.9. Harus ada setidaknya satu inisialisasi. Dijelaskan di sini: stackoverflow.com/questions/17589533/… . Khususnya { initializer-list }kemudian daftar penginisialisasi: designation(opt) initializeratauinitializer-list , designation(opt) initializer
Lundin
2
@Lundin Dalam contoh khusus ini, tidak tahu. Tetapi ekstensi gcc digunakan secara luas di kernel linux.
bobsburner
20

Anda mungkin terbiasa dengan string tanpa-penghentian nol. ctl_table ip_ct_sysctl_table[]adalah array yang diakhiri nol, yaitu entri array terakhir memiliki semua anggota nol.

MSalters
sumber
1
Jadi melalui array, Anda tahu Anda telah mencapai akhir ketika misalnya procnamenol, atau maxlennol.
Paul Ogilvie
1
@ PaulOgilvie: Ya, contohnya tidak lengkap. procnamebisa char[100]dalam hal ini "", bukan nol. Tetapi sebaliknya ya.
MSalters
13

Apa perlunya kawat gigi kosong '{}' di akhir array struct?

Agar lebih jelas: "kurung kosong '{}' di akhir array struct" tidak diperlukan untuk memenuhi persyaratan sintaksis C.

Kapan saya harus menggunakan kawat gigi kosong di akhir array struct?

Ketika kode menginginkan nilai sentinel .

Terkadang berguna bagi program untuk memiliki elemen array final dari semua nol - tentu saja untuk mendeteksi akhirnya. The perlu datang dari penggunaan aplikasi array ctl_table ip_ct_sysctl_table[], bukan dari kebutuhan bahasa C.

chux - Pasang kembali Monica
sumber
9

Ini adalah nol elemen yang diinisialisasi pada akhir array untuk meningkatkan jumlah elemen array dengan satu.

Pertimbangkan demo kecil ini:

#include <stdio.h>

struct Test
{
  int x;
  int y;
} arr[] =
{
    {1,2},
    {3,4},
//  {}
};

int main(void) {
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

Ukuran arrarray akan berubah jika Anda menghapus tanda komentar {}pada akhir daftar inisialisasi array.

Output:

Dengan // {}(array memiliki 2 elemen)

2

Dengan {}(array memiliki 3 elemen)

3

Penjelasan lebih lanjut:

The ip_ct_sysctl_tablearray hanya digunakan di satu tempat, yang ada di sini:

in->ctl_table = kmemdup(ip_ct_sysctl_table,
                sizeof(ip_ct_sysctl_table),
                GFP_KERNEL);

Ekstra {}meningkatkan ukuran total ip_ct_sysctl_table.

Jabberwocky
sumber
1
Itu bukan "untuk meningkatkan jumlah elemen array" tetapi untuk memberi sinyal akhir array.
Paul Ogilvie
6
LOL, tidak. Idenya adalah bahwa tidak ada yang sejauh ini mampu menjelaskannya sepenuhnya, dengan kepastian mutlak. Pernyataan kepastian terdekat adalah bahwa { }penginisialisasi. Namun mengapa masih belum jelas. Jadi, untuk sekarang, kata mungkin adalah mungkin ide yang baik. :)
ryyker