ทำไมไวยากรณ์ BNF ของ C อนุญาตการประกาศด้วยชุดคำสั่ง init ที่ว่างเปล่า


28

เมื่อมองผ่าน BNF ไวยากรณ์ของ C ฉันคิดว่ามันแปลกที่กฎการผลิตสำหรับการประกาศมีลักษณะเช่นนี้ (ตามhttps://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ):

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

ใช้ทำไม*ปริมาณ (หมายถึงศูนย์หรือมากกว่าเกิดขึ้น) สำหรับinit-declarator? สิ่งนี้อนุญาตให้ใช้ข้อความเช่นint;หรือvoid;เพื่อให้มีความถูกต้องทางไวยากรณ์แม้ว่าจะไม่ถูกต้องทางอรรถศาสตร์ พวกเขาไม่สามารถใช้ตัว+นับจำนวน (อย่างน้อยหนึ่งเหตุการณ์) แทน*กฎการผลิตได้หรือไม่

ฉันพยายามคอมไพล์โปรแกรมอย่างง่ายเพื่อดูว่าคอมไพเลอร์เอาท์พุทอะไรและมันทำอะไรเป็นคำเตือน

การป้อนข้อมูล:

int main(void) {
    int;
}

เอาท์พุท:

test.c: In function main’:
test.c:2:5: warning: useless type name in empty declaration
     int;
     ^~~

2
ความแตกต่างคือ BNF เท่านั้นกำหนดไวยากรณ์ มีหลายสิ่งหลายอย่างที่ได้รับอนุญาตจาก syntactically แต่ก็ยังคงไม่ถูกต้อง (หรือไร้สาระ) C. พบว่าดี!
larkey

7
อ่าและโปรดใช้intเป็นประเภทส่งคืนmainและไม่ใช้()เป็นรายการประเภทพารามิเตอร์ในฟังก์ชั่น แต่(void)ใช้แทน
larkey

1
แนวคิดไม่มีอะไรผิดปกติกับสิ่งนี้ยกเว้นว่าฟังดูตลกนิดหน่อย: โดยทั่วไปมันจะถามคอมพิวเตอร์ว่า "ฉันต้องการตัวแปร int ไม่เป็นศูนย์โปรดชื่อ: [emptyset]" คุณสามารถถามแอปเปิ้ลเป็นศูนย์ได้เลย (แม้ว่ามันจะทำให้เกิดปฏิกิริยาที่น่าสนใจกว่าการถามสักหน่อย แต่มันไม่ใช่คำพูดที่ไร้สาระโดยเนื้อแท้) เหตุใดจึงไม่ควรใช้ไวยากรณ์ใน C ไม่มีอะไรผิดกับไวยากรณ์ประเภทนี้
The_Sympathizer

บ่อยครั้งที่สิ่งต่าง ๆ ใช้งานได้ดีกว่ามากเมื่อเรารวมกรณีที่ว่าง (หรืออาจเป็นสุญญากาศ) ไปด้วย
The_Sympathizer

บางครั้งมันไม่ใช่มนุษย์ที่เขียนโปรแกรม แต่เป็นโปรแกรมอื่น บางครั้งโปรแกรมดังกล่าวอาจต้องการพิมพ์ "int" ตามด้วยรายการที่คั่นด้วยเครื่องหมายจุลภาค o evthames ที่เราต้องการตามด้วย ";" และมีความสุขที่ไม่จำเป็นต้องตรวจสอบว่ารายการดังกล่าวว่างเปล่าก่อน
Hagen von Eitzen

คำตอบ:


29

declaration-specifierรวมซึ่งรวมถึงtype-specifier enum-specifierโครงสร้างเหมือน

enum stuff {x, y};

เป็นที่ถูกต้องไม่มีdeclarationinit-declarator

โครงสร้างเช่นint;นั้นถูกตัดออกโดยข้อ จำกัด นอกเหนือจากไวยากรณ์ :

การประกาศอื่น ๆ นอกเหนือจากการประกาศ static_assert จะต้องประกาศอย่างน้อยผู้ประกาศ (นอกเหนือจากพารามิเตอร์ของฟังก์ชั่นหรือสมาชิกของโครงสร้างหรือสหภาพ) แท็กหรือสมาชิกของการแจงนับ

ฉันเดาว่ามีเหตุผลด้านความเข้ากันได้แบบย้อนหลังที่อยู่เบื้องหลังคอมไพเลอร์ของคุณเท่านั้นที่ออกคำเตือน


14

การประกาศที่ไม่มีตัวประกาศ init:

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

ไม่เป็นอันตรายสำหรับรายการตัวระบุการประกาศที่ไม่ใช่ตัวenum/ struct/ ตัวunionระบุเดียวและจะตรงกับที่เป็นประโยชน์

ไม่ว่าในกรณีใดไวยากรณ์ที่นำเสนอจะตรงกับการประกาศเช่นint struct foo x;หรือdouble _Bool y;(อนุญาตให้ตัวระบุหลายตัวเพื่อจับคู่สิ่งต่าง ๆ เช่นlong long int) แต่สิ่งเหล่านี้สามารถตรวจพบได้ในภายหลังในการตรวจสอบความหมาย

ไวยากรณ์ของ BNF นั้นจะไม่กำจัดสิ่งก่อสร้างที่ผิดกฎหมายทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.