พิจารณานิยามฟังก์ชันทั้งสองนี้:
void foo() { }
void foo(void) { }
มีความแตกต่างระหว่างสองคนนี้ไหม? ถ้าไม่เป็นเช่นนั้นทำไมจึงมีการvoid
โต้แย้ง? เหตุผลด้านความงาม?
พิจารณานิยามฟังก์ชันทั้งสองนี้:
void foo() { }
void foo(void) { }
มีความแตกต่างระหว่างสองคนนี้ไหม? ถ้าไม่เป็นเช่นนั้นทำไมจึงมีการvoid
โต้แย้ง? เหตุผลด้านความงาม?
คำตอบ:
ในC :
void foo()
หมายถึง "ฟังก์ชั่นที่foo
รับจำนวนอาร์กิวเมนต์ที่ไม่ระบุชนิดที่ไม่ระบุ" void foo(void)
หมายถึง "ฟังก์ชั่นที่foo
ไม่มีข้อโต้แย้ง"ในC ++ :
void foo()
หมายถึง "ฟังก์ชั่นที่foo
ไม่มีข้อโต้แย้ง" void foo(void)
หมายถึง "ฟังก์ชั่นที่foo
ไม่มีข้อโต้แย้ง"โดยการเขียนfoo(void)
ดังนั้นเราบรรลุความหมายเดียวกันในทั้งสองภาษาและทำให้ส่วนหัวของเราพูดได้หลายภาษา (แม้ว่าเรามักจะต้องทำบางสิ่งบางอย่างมากขึ้นในส่วนหัวจะทำให้พวกเขาอย่างแท้จริงข้ามภาษา ได้แก่ ห่อไว้ในextern "C"
ถ้าเรารวบรวมกำลัง C ++)
void
มันจะสามารถหลีกเลี่ยงปัญหา "การทำให้กระจ่างที่สุด" ได้
void foo()
เป็นเพียงไวยากรณ์เดียวที่ประกาศฟังก์ชัน เมื่อมีลายเซ็นที่แนะนำคณะกรรมการ C จะต้องทำให้กระจ่างไม่มีพารามิเตอร์จากไวยากรณ์เก่าและแนะนำvoid foo(void)
ไวยากรณ์ C ++ ใช้เพื่อความเข้ากันได้
void foo()
แทนvoid foo(void)
จะสร้างความแตกต่างในการทำงาน คือฉันเคยใช้เวอร์ชั่นโดยไม่มีช่องว่างเป็นเวลาหลายปีและไม่เห็นปัญหาใด ๆ ฉันขาดอะไรไปหรือเปล่า?
void foo() { if ( rand() ) foo(5); }
รวบรวมและเรียกใช้ (ก่อให้เกิดพฤติกรรมที่ไม่ได้กำหนดเว้นแต่ว่าคุณโชคดีมาก) ในขณะvoid foo(void)
ที่เนื้อหาเดียวกันจะทำให้เกิดข้อผิดพลาดในการรวบรวม
ฉันรู้ว่าคำถามของคุณเกี่ยวข้องกับ C ++ แต่เมื่อพูดถึง C คำตอบสามารถพบได้ใน K&R หน้า 72-73:
นอกจากนี้หากการประกาศฟังก์ชั่นไม่รวมถึงข้อโต้แย้งตามที่
double atof();
นั่นก็หมายความว่าไม่มีอะไรที่จะต้องคิดเรื่องการโต้เถียงของ atof; การตรวจสอบพารามิเตอร์ทั้งหมดถูกปิด ความหมายพิเศษของรายการอาร์กิวเมนต์ว่างนี้มีวัตถุประสงค์เพื่ออนุญาตให้โปรแกรม C รุ่นเก่าคอมไพล์ด้วยคอมไพเลอร์ใหม่ แต่มันเป็นความคิดที่ดีที่จะใช้กับโปรแกรมใหม่ หากฟังก์ชันรับอาร์กิวเมนต์ให้ประกาศ; หากไม่มีข้อโต้แย้งให้ใช้โมฆะ
ร่างมาตรฐาน C ++ 11 N3337
ไม่มีความแตกต่าง
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
ภาคผนวก C "ความเข้ากันได้" C.1.7 ข้อ 8: ผู้ประกาศบอกว่า:
8.3.5 การเปลี่ยนแปลง: ใน C ++ ฟังก์ชั่นที่ประกาศพร้อมรายการพารามิเตอร์ว่างจะไม่มีข้อโต้แย้ง ใน C รายการพารามิเตอร์ว่างหมายความว่าไม่ทราบจำนวนและชนิดของอาร์กิวเมนต์ของฟังก์ชัน
ตัวอย่าง:
int f(); // means int f(void) in C ++ // int f( unknown ) in C
เหตุผล: เพื่อหลีกเลี่ยงการเรียกใช้ฟังก์ชันที่ผิดพลาด (เช่นการเรียกใช้ฟังก์ชันที่มีหมายเลขหรือประเภทของอาร์กิวเมนต์ที่ไม่ถูกต้อง)
ผลต่อคุณสมบัติดั้งเดิม: เปลี่ยนความหมายของคุณสมบัติที่กำหนดไว้อย่างดี สถานที่นี้ถูกทำเครื่องหมายว่า "ล้าสมัย" ใน C
ฟังก์ชั่น 8.5.3พูดว่า:
4. พารามิเตอร์-declaration-clause กำหนดอาร์กิวเมนต์ที่สามารถระบุได้และการประมวลผลของมันเมื่อเรียกใช้ฟังก์ชัน [... ] หาก parameter-declaration-clause ว่างเปล่าฟังก์ชันจะไม่มีข้อโต้แย้ง รายการพารามิเตอร์ (void) เทียบเท่ากับรายการพารามิเตอร์เปล่า
C99
ตามที่กล่าวไว้โดย C ++ 11 ไม่ได้int f()
ระบุอะไรเกี่ยวกับข้อโต้แย้งและล้าสมัย
มันสามารถนำไปสู่รหัสการทำงานหรือ UB
ฉันได้ตีความรายละเอียดมาตรฐาน C99 ที่: https://stackoverflow.com/a/36292431/895245
ใน C คุณใช้ช่องว่างในการอ้างอิงฟังก์ชันว่างเพื่อให้คอมไพเลอร์มีต้นแบบและต้นแบบนั้นไม่มี "อาร์กิวเมนต์" ใน C ++ คุณไม่ต้องบอกคอมไพเลอร์ว่าคุณมีต้นแบบเพราะคุณไม่สามารถออกจากต้นแบบได้