โมฆะหมายถึงอะไรใน C, C ++ และ C #


170

การมองหาพื้นฐานที่คำว่า " โมฆะ " มาจากไหนและทำไมจึงเรียกว่าโมฆะ จุดประสงค์ของคำถามคือช่วยคนที่ไม่มีประสบการณ์เกี่ยวกับ C และจู่ๆก็มองไปที่ codebase บนพื้นฐานของ C


2
คำถามนี้ผสมผสาน 3 ภาษา ... คำถามดั้งเดิมควรแบ่งเป็น 3 คำถามที่แตกต่างกัน
Stargateur

คำตอบ:


225

โดยทั่วไปมันหมายถึง "ไม่มีอะไร" หรือ "ไม่มีประเภท"

มี 3 วิธีพื้นฐานที่ใช้เป็นโมฆะ:

  1. อาร์กิวเมนต์ของฟังก์ชัน: int myFunc(void) - ฟังก์ชันไม่ทำอะไรเลย

  2. ฟังก์ชั่นคืนค่า: void myFunc(int) - ฟังก์ชั่นคืนค่าอะไร

  3. ตัวชี้ข้อมูลทั่วไป: void* data - 'data' เป็นตัวชี้ไปยังข้อมูลประเภทที่ไม่รู้จักและไม่สามารถถูกปฏิเสธได้

หมายเหตุ: voidอาร์กิวเมนต์ในฟังก์ชั่นเป็นตัวเลือกใน C ++ ดังนั้นจึงint myFunc()เป็นเช่นเดียวกับint myFunc(void)และมันถูกทิ้งไว้อย่างสมบูรณ์ใน C # มันจำเป็นสำหรับค่าส่งคืนเสมอ


7
ถือเป็นโมฆะในรายการอาร์กิวเมนต์เป็นตัวเลือกใน C ++, ดูstackoverflow.com/questions/416345/…
Daniel Earwicker

1
ฉันต้องการใช้ "ไม่มีประเภท" มากกว่า "ขนาดไม่"
เคอร์วิน Joergensen

@Earwicker และ kjetijor ทั้งข้อดีและข้อเสียของฉัน
เจอราลด์

9
ไม่เห็นด้วย แต่การใช้ช่องว่างเพิ่มเติมนั้นอยู่ในเคล็ดลับ "cast to void" เพื่อระงับการเตือนสำหรับค่าที่ไม่ได้ใช้ มันค่อนข้างยืดเพราะมันไม่สอดคล้องกับวิธีที่คอมไพเลอร์ตีความสิ่งต่าง ๆ แต่คุณสามารถตีความได้ว่าหมายถึง "ฉันใช้ค่านี้เพื่อไม่ทำอะไรเลย"
Steve Jessop

22
ใน C ++ โมฆะในรายการอาร์กิวเมนต์เป็นตัวเลือก อย่างไรก็ตามใน C ไม่ใช่ทางเลือก: foo () หมายถึงใช้พารามิเตอร์จำนวนเท่าใดก็ได้ในขณะที่ foo (void) หมายถึงใช้พารามิเตอร์เป็นศูนย์
Adam Rosenfield

33

ฉันได้นำเสมอว่ามันหมายถึงขาด ต่อไปนี้เป็นสี่กรณีในภาษา C ที่ตรงกับการใช้งานที่ไม่มีอยู่

  • R f(void)- ขาดฟังก์ชั่นพารามิเตอร์
  • void f(P)- ค่าที่ส่งกลับคือขาด
  • void *p- ประเภทของสิ่งที่ชี้ไปยังขาดอยู่
  • (void) p- ขาดการใช้งานมูลค่า

ลูกหลาน C คนอื่นใช้มันเพื่อสิ่งอื่น Dภาษาการเขียนโปรแกรมใช้มันสำหรับกรณีที่ซึ่งการเริ่มต้นคือขาด

  • T t = void;- ค่าเริ่มต้นคือขาด

4
อะไร(void)pทำอย่างไร ฉันไม่ได้รับสิ่งที่คุณหมายถึงโดย "การใช้งานของมูลค่าขาด"
Yashas

@Yashas ถ้าใครยังสับสนเกี่ยวกับ(void) var;คำสั่งฉันได้พบคำตอบรายละเอียดที่stackoverflow.com/q/21045615
Arnie97

14

มีสองวิธีในการใช้ช่องว่าง:

void foo(void);

หรือ

void *bar(void*);

ตัวแรกระบุว่าไม่มีการส่งผ่านอาร์กิวเมนต์หรือไม่มีการส่งคืนอาร์กิวเมนต์

ที่สองบอกคอมไพเลอร์ว่าไม่มีประเภทที่เกี่ยวข้องกับข้อมูลได้อย่างมีประสิทธิภาพซึ่งหมายความว่าคุณไม่สามารถใช้ข้อมูลที่ชี้ไปจนกว่าจะส่งไปยังประเภทที่รู้จัก

ตัวอย่างเช่นคุณจะเห็นการvoid*ใช้งานจำนวนมากเมื่อคุณมีอินเทอร์เฟซที่เรียกใช้ฟังก์ชันซึ่งพารามิเตอร์ไม่สามารถทราบล่วงหน้าได้

ตัวอย่างเช่นในเคอร์เนล Linux เมื่อเลื่อนการทำงานคุณจะตั้งค่าฟังก์ชั่นที่จะทำงานในเวลาต่อมาโดยให้มันเป็นตัวชี้ไปยังฟังก์ชั่นที่จะทำงานและตัวชี้ไปยังข้อมูลที่จะส่งผ่านไปยังฟังก์ชั่น:

struct _deferred_work {
sruct list_head mylist;
.worker_func = bar;
.data        = somedata;
} deferred_work;

จากนั้นเคอร์เนลเธรดจะผ่านรายการของงานที่ถูกเลื่อนออกไปและเมื่อมันไปถึงโหนดนี้มันจะทำงานได้อย่างมีประสิทธิภาพ:

bar(somedata);

จากนั้นในบาร์คุณมี:

void bar(void* mydata) {
    int *data = mydata;
    /* do something with data */;
}

13

มันหมายถึง "ไม่มีค่า" คุณใช้voidเพื่อระบุว่าฟังก์ชันไม่ส่งคืนค่าหรือไม่มีพารามิเตอร์หรือทั้งสองอย่าง ค่อนข้างสอดคล้องกับการใช้คำในภาษาอังกฤษเป็นโมฆะ


4

มันบ่งบอกถึงการไม่มีค่าตอบแทนในฟังก์ชั่น

บางภาษามีรูทีนย่อยสองประเภท: ขั้นตอนและฟังก์ชั่น ขั้นตอนเป็นเพียงลำดับของการดำเนินการในขณะที่ฟังก์ชั่นเป็นลำดับของการดำเนินการที่ส่งกลับผลลัพธ์

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


3

คิดว่าเป็นโมฆะในฐานะ "โครงสร้างที่ว่างเปล่า" ให้ฉันอธิบาย

ทุกฟังก์ชั่นใช้ลำดับของพารามิเตอร์โดยที่แต่ละพารามิเตอร์มีประเภท ในความเป็นจริงเราสามารถรวมพารามิเตอร์เข้าไปในโครงสร้างด้วยสล็อตโครงสร้างที่สอดคล้องกับพารามิเตอร์ ทำให้ทุกฟังก์ชั่นมีอาร์กิวเมนต์เดียว ในทำนองเดียวกันฟังก์ชั่นสร้างผลลัพธ์ซึ่งมีประเภท มันอาจเป็นบูลีนหรืออาจลอยหรืออาจเป็นโครงสร้างที่มีชุดค่าพิมพ์อื่นโดยพลการ ถ้าเราต้องการ languge ที่มีค่าส่งคืนหลายค่ามันเป็นเรื่องง่ายเพียงแค่ยืนยันว่าพวกเขาจะถูกบรรจุลงในโครงสร้าง ในความเป็นจริงเราสามารถยืนยันได้เสมอว่าฟังก์ชั่นคืนโครงสร้าง ตอนนี้ทุกฟังก์ชั่นรับอาร์กิวเมนต์เดียวและสร้างหนึ่งค่า

ตอนนี้จะเกิดอะไรขึ้นเมื่อฉันต้องการฟังก์ชั่นที่สร้างค่า "ไม่" เอาล่ะลองพิจารณาสิ่งที่ฉันได้รับเมื่อสร้างโครงสร้างที่มี 3 สล็อต: มันมีค่า 3 ค่า เมื่อฉันมี 2 สล็อตมันเก็บค่าสองค่า เมื่อมันมีหนึ่งช่องหนึ่งค่า และเมื่อมันมีช่องว่างเป็นศูนย์ก็จะถือ ... เอ่อ, ค่าศูนย์หรือ "ไม่มี" ค่า "ดังนั้นฉันสามารถคิดว่าฟังก์ชั่นกลับเป็นโมฆะเป็นคืนโครงสร้างที่มีค่าไม่มีคุณยังสามารถตัดสินใจว่า" โมฆะ " เป็นเพียงคำพ้องความหมายสำหรับประเภทที่แสดงโดยโครงสร้างที่ว่างเปล่ามากกว่าคำหลักในภาษา (อาจเป็นเพียงประเภทที่กำหนดไว้ล่วงหน้า :)

ในทำนองเดียวกันฉันสามารถคิดได้ว่าฟังก์ชั่นที่ไม่ต้องการค่าใด ๆ เป็นการยอมรับโครงสร้างที่ว่างเปล่าเช่น "void"

ฉันยังสามารถใช้ภาษาโปรแกรมของฉันด้วยวิธีนี้ การส่งค่าเป็นโมฆะใช้เวลาเป็นศูนย์ไบต์ดังนั้นการผ่านค่าโมฆะเป็นเพียงกรณีพิเศษในการส่งผ่านค่าอื่น ๆ ที่มีขนาดตามอำเภอใจ สิ่งนี้ทำให้ง่ายสำหรับคอมไพเลอร์ในการรักษาผลหรือโมฆะ "โมฆะ" คุณอาจต้องการฟีเจอร์ที่ทำให้ฟังก์ชั่นหลุดออกไป ใน C ถ้าคุณเรียกใช้ฟังก์ชันผลลัพธ์ non-void foo ในคำสั่งต่อไปนี้: foo (... ); คอมไพเลอร์รู้ว่าฟูสร้างผลลัพธ์และไม่สนใจเลย ถ้าเป็นโมฆะเป็นค่าการทำงานอย่างสมบูรณ์แบบและตอนนี้ "ขั้นตอน" (ซึ่งเป็นเพียงคำคุณศัพท์สำหรับฟังก์ชั่นที่มีผลเป็นโมฆะ) เป็นเพียงกรณีพิเศษเล็กน้อยของฟังก์ชั่นทั่วไป

Void * สนุกขึ้นเล็กน้อย ฉันไม่คิดว่านักออกแบบ C คิดว่าเป็นโมฆะในวิธีข้างต้น พวกเขาเพิ่งสร้างคำหลัก คำหลักนั้นพร้อมใช้งานเมื่อมีคนต้องการชี้ไปที่ประเภทที่กำหนดเองจึงเป็นโมฆะ * เป็นสำนวนใน C. มันใช้งานได้ดีจริง ๆ ถ้าคุณตีความโมฆะว่าเป็นโครงสร้างที่ว่างเปล่า ตัวชี้โมฆะ * คือที่อยู่ของสถานที่ซึ่งวางโครงสร้างว่างไว้

ปลดเปลื้องจากโมฆะ * เป็น T * สำหรับประเภทอื่น T ยังทำงานกับมุมมองนี้ ตัวชี้การร่ายเป็นสูตรสมบูรณ์ที่ทำงานบนสถาปัตยกรรมทั่วไปส่วนใหญ่เพื่อใช้ประโยชน์จากความจริงที่ว่าถ้าชนิดผสม T มีองค์ประกอบที่มีชนิดย่อย S วางทางกายภาพที่จุดเริ่มต้นของ T ในรูปแบบการจัดเก็บแล้วหล่อ S * ถึง T * และ ในทางกลับกันโดยใช้ที่อยู่ทางกายภาพของเครื่องเดียวกันมีแนวโน้มที่จะทำงานออกมาเนื่องจากตัวชี้ของเครื่องส่วนใหญ่มีการแสดงเพียงครั้งเดียว การแทนที่ type S ด้วยโมฆะ type นั้นให้ผลเหมือนกันทุกประการดังนั้นการร่ายไปยัง / จาก void * จะได้ผล

ภาษาการเขียนโปรแกรม PARLANSE ใช้ความคิดข้างต้นอย่างใกล้ชิด เราหลงทางในการออกแบบและไม่ใส่ใจกับ "โมฆะ" ในฐานะประเภทส่งคืนและมีคำหลักที่เป็นคำแนะนำสำหรับกระบวนการ ส่วนใหญ่เป็นเพียงการเปลี่ยนแปลงทางไวยากรณ์อย่างง่าย แต่สิ่งหนึ่งที่คุณไม่ได้ทำเมื่อคุณได้รับรหัสการทำงานที่ใหญ่ในภาษา


2

ใน c # คุณจะต้องใช้คำหลักที่เป็นโมฆะเพื่อระบุว่าวิธีการใดไม่ส่งคืนค่า:

public void DoSomeWork()
{
//some work
}

4
คนส่วนใหญ่ไม่ทราบว่าแผนที่เป็นโมฆะไป System.Void โครงสรmsdn.microsoft.com/en-us/library/system.void.aspx
RichardOD

2

กรณีการใช้งานสามกรณีสำหรับโมฆะ:

  1. ฟังก์ชั่นลายเซ็นต์ void foo(int bar)ไม่ส่งคืนค่า int bar(void)ไม่ใช้พารามิเตอร์ใด ๆ int bar()แต่นี้มักจะแสดงกับรายการอาร์กิวเมนต์ที่ว่างเปล่า การใช้คำสำคัญเป็นโมฆะที่นี่ตรงกับความหมายในภาษาอังกฤษ

  2. ตัวชี้ชนิดด้านบนทั่วไปvoid *ที่ชี้ไปยังข้อมูลที่ไม่ระบุและไม่สามารถยกเลิกการลงทะเบียนได้ ที่นี่ความหมายของโมฆะแตกต่างจากความหมายอื่น ๆ ของโมฆะ: ประเภทสากลกับไม่มีประเภท

  3. ในการปลดเปลื้องเช่น(void) new Foo(this)มีความหมายว่ามูลค่าส่งคืนจะถูกโยนทิ้งไปอย่างจงใจ นี่คือการใช้คำหลักตรงกับความหมายในภาษาอังกฤษ

กรณีที่ 1 และ 2 ถูกครอบคลุมโดย @Gerald แต่กรณีที่ 3 ยังไม่ได้รับการแก้ไข


2

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

มันมักจะปรากฏในรหัสที่โดยปกติคุณคาดว่าจะเห็นประเภทปรากฏขึ้นเช่นประเภทกลับหรือประเภทตัวชี้ นี่คือเหตุผลใน C # โมฆะแมปประเภท CLR จริง System.Void เนื่องจากเป็นชนิดในตัวเอง

ภาษาการเขียนโปรแกรมบางภาษาไม่เคยพัฒนาแนวคิดเกี่ยวกับความว่างเปล่าเช่นเดียวกับวัฒนธรรมของมนุษย์บางคนที่ไม่เคยคิดค้นแนวคิดของเลขศูนย์ โมฆะแสดงถึงความก้าวหน้าในภาษาโปรแกรมเหมือนกับแนวคิดของ zero หมายถึงภาษามนุษย์


เพียงทราบเกี่ยวกับประโยคสุดท้ายของคุณ - จำไว้ว่าเป็นจริงของภาษาที่พิมพ์แบบคงที่ ภาษาที่พิมพ์แบบไดนามิกไม่จำเป็นต้องมีโมฆะเนื่องจากวิธีการของพวกเขาอาจจะไม่คืนสิ่งใดเลย - "โมฆะ" นั้นถูกบอกเป็นนัยจากการที่ไม่มีสิ่งใดถูกส่งคืน
ทำเครื่องหมาย Embling

การแก้ไขความคิดเห็นล่าสุดของฉัน - ฉันหมายถึงการพูดย่อหน้าสุดท้าย (ไม่ใช่ประโยค)
ทำเครื่องหมาย Embling

1

มันหมายถึง "ไม่มีค่า" คุณใช้โมฆะเพื่อระบุว่าฟังก์ชั่นไม่ส่งคืนค่าหรือไม่มีพารามิเตอร์หรือทั้งสองอย่างมันสอดคล้องกับการใช้คำว่าโมฆะในภาษาอังกฤษโดยทั่วไป

โมฆะไม่ควรสับสนกับ null Null หมายถึงตัวแปรที่มีที่อยู่บนสแต็กค่าบนฮีปสำหรับที่อยู่นั้นว่างเปล่า


0

โมฆะใช้ในลายเซ็นวิธีเท่านั้น สำหรับประเภทการส่งคืนหมายถึงวิธีการจะไม่ส่งคืนรหัสใด ๆ สำหรับพารามิเตอร์หมายความว่าจะไม่มีการส่งพารามิเตอร์ไปยังเมธอด

เช่น

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

ใน C # เราสามารถละเว้นโมฆะสำหรับพารามิเตอร์และสามารถเขียนโค้ดข้างต้นเป็น:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

โมฆะไม่ควรสับสนกับ null Null หมายถึงตัวแปรที่มีที่อยู่บนสแต็กค่าบนฮีปสำหรับที่อยู่นั้นว่างเปล่า


0

Void เป็นชนิดที่ไม่สมบูรณ์ซึ่งตามนิยามแล้วจะไม่สามารถเป็น lvalue ได้ นั่นหมายความว่าไม่สามารถกำหนดค่าได้

ดังนั้นจึงไม่สามารถเก็บค่าใด ๆ


-1

ถือเป็นโมฆะหมายความว่าคุณจะไม่ส่งคืนค่าใด ๆ ในรูปแบบฟังก์ชั่นหรือวิธีการ


-1

Void หมายถึงไม่จำเป็นต้องใช้ค่าในประเภทส่งคืนจากฟังก์ชันในทั้งสามภาษา


-1

Void เทียบเท่ากับ Sub ของ Visual Basic


เป็นชนิดที่ส่งคืนเท่านั้น ฉันสามารถนึกถึงการใช้โมฆะอีกสามครั้ง: อาร์กิวเมนต์เป็นโมฆะ (ฟังก์ชันไม่ทำอะไรเลย), ตัวชี้โมฆะ (ไม่ได้ระบุประเภทตัวชี้) และโมฆะ casts (ค่าทิ้ง)
c4757p
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.