Mengapa tata bahasa BNF C memungkinkan deklarasi dengan deretan init-deklarator kosong?

28

Ketika melihat melalui tata bahasa BNF C, saya pikir itu aneh bahwa aturan produksi untuk deklarasi terlihat seperti ini (menurut https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20di% 20Backus-Naur% 20form.htm ):

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

Mengapa menggunakan *quantifier (artinya nol atau lebih kejadian) untuk init-declarator? Ini memungkinkan pernyataan seperti int;atau void;menjadi valid secara sintaksis, meskipun secara semantik tidak valid. Tidak bisakah mereka menggunakan +kuantifier (satu kejadian atau lebih) daripada *dalam aturan produksi?

Saya mencoba mengkompilasi program sederhana untuk melihat apa yang dihasilkan oleh kompiler dan yang dilakukannya hanyalah mengeluarkan peringatan.

Memasukkan:

int main(void) {
    int;
}

Keluaran:

test.c: In function main’:
test.c:2:5: warning: useless type name in empty declaration
     int;
     ^~~
rafaelfp
sumber
2
Perbedaannya adalah bahwa BNF hanya mendefinisikan sintaks. Cukup banyak hal yang diizinkan secara sintaksis tetapi masih tidak valid (atau tidak masuk akal) C. Namun, sangat menyenangkan!
larkey
7
Ah, dan tolong gunakan intsebagai tipe pengembalian untuk maindan jangan gunakan ()sebagai daftar jenis parameter dalam fungsi tetapi (void)sebagai gantinya.
larkey
1
Secara konseptual , tidak ada yang benar-benar salah dengan ini kecuali kedengarannya agak lucu: pada dasarnya bertanya pada komputer "Saya ingin variabel nol int, tolong, nama: [emptyset].". Lagipula, Anda dapat meminta seseorang untuk nol apel (meskipun kemungkinan akan menimbulkan reaksi yang sedikit lebih menarik daripada meminta satu apel, tetapi itu bukan pernyataan yang secara inheren tidak masuk akal). Karena itu mengapa harus ungrammatical di C? Tidak ada yang salah dengan tata bahasa semacam ini.
The_Sympathizer
Sangat sering hal-hal bekerja jauh lebih baik ketika kita memasukkan kasus hampa (atau mungkin, vakum?).
The_Sympathizer
Terkadang bukan manusia yang menulis program, tetapi program lain. Program seperti itu kadang-kadang mungkin ingin mencetak "int" diikuti oleh daftar yang dipisahkan koma dari evarnames yang kita butuhkan, diikuti oleh ";" dan senang tidak perlu memeriksa apakah daftar tersebut kosong terlebih dahulu.
Hagen von Eitzen

Jawaban:

29

declaration-specifiertermasuk type-specifier, yang termasuk enum-specifier. Konstruk seperti

enum stuff {x, y};

valid declarationdengan no init-declarator.

Konstruksi seperti int;dikesampingkan oleh kendala di luar tata bahasa :

Deklarasi selain deklarasi static_assert harus mendeklarasikan paling tidak deklarator (selain parameter fungsi atau anggota struktur atau gabungan), tag, atau anggota enumerasi.

Saya kira ada alasan kompatibilitas di belakang kompiler Anda hanya mengeluarkan peringatan.

user2357112 mendukung Monica
sumber
14

Deklarasi tanpa deklarasi init:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

tidak berbahaya untuk daftar specifier deklarasi yang bukan satu enum/ struct/ unionspecifier dan berguna sesuai dengan yang ada.

Dalam setiap kasus, tata bahasa yang disajikan juga akan secara keliru mencocokkan deklarasi seperti int struct foo x;atau double _Bool y;(memungkinkan beberapa penspesifikasi untuk mencocokkan hal-hal seperti long long int), tetapi semua ini dapat dideteksi kemudian, dalam pemeriksaan semantik.

Tata bahasa BNF itu sendiri tidak akan menyingkirkan semua konstruksi ilegal.

PSkocik
sumber