ความแตกต่างระหว่าง function () และ function (void) คืออะไร?


27

ฉันเคยได้ยินว่ามันเป็นวิธีปฏิบัติที่ดีในการเขียนฟังก์ชั่นที่ไม่ได้รับอะไรเป็นพารามิเตอร์เช่นนี้:

int func(void);

แต่ฉันได้ยินว่าวิธีที่ถูกต้องในการแสดงออกเช่นนี้:

int func();

ความแตกต่างระหว่างการประกาศฟังก์ชั่นทั้งสองนี้ในทั้ง C และ C ++ คืออะไร?


5
นี่เป็นคำถามซ้ำ ๆ กันหลายพันคำถามในเครือข่ายไซต์stackoverflow.com/questions/18167390/…
Lars Viklund

@LarsViklund เป็นเพียงข้อมูลซ้ำซ้อนหากมีคำถามในไซต์นี้ ฉันไม่สามารถค้นหาได้ดังนั้นไม่ว่าจะเป็น SO อะไรก็ตามนี่ไม่ได้ซ้ำกัน อาจคุ้มค่าที่จะเก็บคำถามนี้ไว้เป็นป้ายบอกทางถ้าไม่มีอะไรอื่น


1
@LightnessRacesinOrbit เราพูดคุยกันในการแชทและตัดสินใจที่จะทำให้มันอยู่กับการแก้ไขบางอย่าง

คำตอบ:


17

C และ C ++ แตกต่างกันในส่วนนี้

C 2011 มาตรฐานออนไลน์

6.7.6.3 ฟังก์ชั่นการประกาศ (รวมถึงต้นแบบ)
...
10 กรณีพิเศษของพารามิเตอร์ที่ไม่มีชื่อประเภทvoidเป็นรายการเดียวในรายการระบุว่าฟังก์ชั่นไม่มีพารามิเตอร์
...
14 รายการตัวระบุประกาศเพียงตัวระบุของพารามิเตอร์ของฟังก์ชั่น รายการว่างในตัวประกาศฟังก์ชันที่เป็นส่วนหนึ่งของนิยามของฟังก์ชันนั้นระบุว่าฟังก์ชันนั้นไม่มีพารามิเตอร์ รายการว่างในตัวประกาศฟังก์ชันที่ไม่ได้เป็นส่วนหนึ่งของนิยามของฟังก์ชันนั้นระบุว่าไม่มีข้อมูลเกี่ยวกับจำนวนหรือชนิดของพารามิเตอร์ 145)

กล่าวโดยย่อรายการพารามิเตอร์ที่ว่างเปล่าในการประกาศฟังก์ชั่นบ่งชี้ว่าฟังก์ชั่นใช้จำนวนพารามิเตอร์ที่ไม่ได้ระบุในขณะที่รายการพารามิเตอร์ที่ว่างเปล่าในการกำหนดฟังก์ชั่นบ่งชี้ว่าฟังก์ชั่นไม่มีพารามิเตอร์

T foo( void ); // declaration, foo takes no parameters
T bar();       // declaration, bar takes an *unspecified* number of parameters

T foo( void ) { ... } // definition, foo takes no parameters
T bar() { ... }       // definition, bar takes no parameters

เท่าที่เกี่ยวข้องกับ C คุณไม่ควรใช้รายการตัวระบุที่ว่างเปล่าในการประกาศฟังก์ชันหรือคำจำกัดความ หากฟังก์ชั่นไม่ได้ตั้งใจที่จะใช้พารามิเตอร์ใด ๆ ระบุว่าโดยใช้voidในรายการพารามิเตอร์

ออนไลน์ C ++ มาตรฐาน

8.3.5 ฟังก์ชั่น [dcl.fct]
...
4 พารามิเตอร์-declaration -clauseจะกำหนดอาร์กิวเมนต์ที่สามารถระบุได้และการประมวลผลของมันเมื่อเรียกใช้ฟังก์ชัน [ หมายเหตุ: พารามิเตอร์ประกาศข้อใช้ในการแปลงข้อโต้แย้งที่ระบุไว้ในการเรียกใช้ฟังก์ชัน; ดู 5.2.2 - หมายเหตุท้าย ] หากพารามิเตอร์-declaration-clauseว่างเปล่าฟังก์ชันจะไม่มีข้อโต้แย้ง รายการพารามิเตอร์ประกอบด้วยพารามิเตอร์ที่ไม่มีชื่อเดียวซึ่งเป็นชนิดที่ไม่ขึ้นอยู่กับvoidจะเทียบเท่ากับรายการพารามิเตอร์ที่ว่างเปล่า cv voidยกเว้นกรณีพิเศษนี้พารามิเตอร์จะไม่มีประเภท ถ้าพารามิเตอร์ประกาศ - ข้อยุติด้วยจุดไข่ปลาหรือชุดพารามิเตอร์ฟังก์ชั่น (14.5.3) จำนวนของการขัดแย้งจะต้องเท่ากับหรือมากกว่าจำนวนของพารามิเตอร์ที่ไม่ได้มีอาร์กิวเมนต์เริ่มต้นและไม่ได้แพ็คพารามิเตอร์ฟังก์ชั่น ที่ไหนที่ถูกต้องทางไวยากรณ์และที่ "... " ไม่ได้เป็นส่วนหนึ่งของผู้ประกาศนามธรรม , ", ... " มีความหมายเหมือนกันกับ "... " [ ตัวอย่าง:การประกาศ
    int printf(const char*, ...);
ประกาศฟังก์ชั่นที่สามารถเรียกได้ด้วยตัวเลขและประเภทของอาร์กิวเมนต์ที่แตกต่างกัน
    printf("hello world");
    printf("a=%d b=%d", a, b);
อย่างไรก็ตามอาร์กิวเมนต์แรกจะต้องเป็นประเภทที่สามารถแปลงเป็นตัวอย่างconst char*- end ] [ หมายเหตุ:ส่วนหัวมาตรฐาน<cstdarg>มีกลไกสำหรับการเข้าถึงอาร์กิวเมนต์ที่ส่งผ่านโดยใช้จุดไข่ปลา (ดู 5.2.2 และ 18.10) - บันทึกท้าย ]

ในกรณีของ C ++ voidรายการพารามิเตอร์ที่ว่างเปล่าทั้งในการประกาศหรือคำนิยามที่บ่งชี้ว่าการทำงานจะเกิดการขัดแย้งใดและเทียบเท่ากับการใช้รายการพารามิเตอร์ของ


35

ใน C ฟังก์ชั่นที่มีรายการพารามิเตอร์ว่าง()สามารถใช้อะไรก็ได้สำหรับอาร์กิวเมนต์ อะไรก็ได้ตามตัวอักษร โดยปกติจะใช้เพื่อนำไปใช้กับฟังก์ชั่นซึ่งสามารถรับค่าตัวแปรจำนวนของข้อโต้แย้งได้ แต่ทุกวันนี้ก็ถือว่าดีกว่าที่จะใช้ไวยากรณ์ของจุดไข่ปลาที่ชัดเจนยิ่งขึ้น(...)สำหรับฟังก์ชั่นเหล่านี้

ใน C ฟังก์ชันที่มีรายการพารามิเตอร์ไม่(void)ต้องทำอะไรเลยสำหรับอาร์กิวเมนต์ นั่นหมายความว่าคอมไพเลอร์สามารถบอกคุณได้ว่าคุณทำพลาดไปแล้วหากคุณพยายามส่งบางสิ่งบางอย่าง

ใน C ++ การประกาศฟังก์ชันเหล่านี้เทียบเท่ากัน รายการพารามิเตอร์เปล่าหมายถึง "ไม่มีพารามิเตอร์" เช่นเดียวกับที่voidทำ


Re: "โดยปกติจะใช้เพื่อนำไปใช้กับฟังก์ชั่นที่สามารถใช้อาร์กิวเมนต์จำนวนตัวแปร": คุณแน่ใจเกี่ยวกับเรื่องนี้? ฉันไม่คิดว่าฉันเคยเห็นโปรแกรมที่ใช้รายการพารามิเตอร์อย่างชัดเจนสำหรับการประกาศไปข้างหน้าของฟังก์ชั่นที่ไม่แปรผันและ()สำหรับโปรแกรมที่หลากหลาย คุณมีตัวอย่างของโปรแกรมที่ใช้การประชุมนี้หรือไม่?
ruakh

4
ฟังก์ชัน AC variadic ต้องถูกกำหนดด้วย...ไวยากรณ์และจะต้องมีพารามิเตอร์ที่กำหนดอย่างน้อยหนึ่งพารามิเตอร์ การกำหนดฟังก์ชั่นดังกล่าวด้วย()สาเหตุการทำงานที่ไม่ได้กำหนด - และไม่มีทางที่เนื้อความของฟังก์ชันจะใช้มาโครที่กำหนดไว้ใน<stdarg.h>การอ่านค่าพารามิเตอร์ นี่เป็นกรณีที่เกิดขึ้นตั้งแต่ปี 1989/1990
Keith Thompson

@ KeithThompson: คำถามนี้และคำตอบนี้กำลังพูดถึงการประกาศล่วงหน้าไม่ใช่คำจำกัดความของฟังก์ชั่น
ruakh

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