foo (void) vs foo (void *)


9

ฟังก์ชั่นและการพูด syntactically มีความแตกต่างระหว่างฟังก์ชั่นที่มีต้นแบบint foo(void)และint foo(void *) ?

ฉันรู้ว่าความแตกต่างระหว่างตัวอย่างเช่นint bar(int)และint bar(int *)- หนึ่งของพวกเขากำลังมองหา int และอื่น ๆ ที่กำลังมองหาตัวชี้ int มีvoidพฤติกรรมแบบเดียวกันหรือไม่?


คำตอบของคำถามที่เกี่ยวข้อง: stackoverflow.com/a/1043209/434551
R Sahu


สิ่งที่อาจจะน่าสนใจมากขึ้นคือความแตกต่างระหว่างและfoo(void) foo()
Maxim Egorushkin

คำตอบ:


10

จากคำตอบนี้ในวิศวกรรมซอฟต์แวร์ voidได้รับการปฏิบัติเป็นพิเศษขึ้นอยู่กับวิธีการใช้งาน ในCและC++, voidใช้เพื่อระบุตัวตนของประเภทข้อมูลที่ในขณะที่void *ถูกนำมาใช้เพื่อระบุตัวชี้ที่จุดบางข้อมูล / พื้นที่ในหน่วยความจำที่ไม่ได้มีประเภท void *ไม่สามารถยกเลิกการลงทะเบียนด้วยตนเองได้และจะต้องนำไปใช้กับประเภทอื่นก่อน ไม่จำเป็นต้องหล่อนี้มีความชัดเจนในแต่ต้องอยู่ในอย่างชัดเจนC C++(นี่คือสาเหตุที่เราไม่ส่งค่าส่งคืนของ malloc ซึ่งก็คือvoid *)


เมื่อใช้กับฟังก์ชั่นเป็นพารามิเตอร์voidหมายถึงการขาดทั้งหมดของพารามิเตอร์ใด ๆ และเป็นพารามิเตอร์เดียวที่ได้รับอนุญาต ความพยายามในการใช้ช่องว่างเช่นประเภทตัวแปรหรือรวมอาร์กิวเมนต์อื่น ๆ ทำให้เกิดข้อผิดพลาดของคอมไพเลอร์:

int foo(void, int);     //trying to use "void" as a parameter
int bar(void baz);      //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
       ^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
             ^

มันเป็นไปไม่ได้ในการประกาศตัวแปรด้วยชนิดvoid:

int main(void) {
  void qux;         //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
  void qux;

voidเป็นค่าตอบแทนสำหรับฟังก์ชั่นบ่งชี้ว่าไม่มีข้อมูลจะถูกส่งกลับ เนื่องจากเป็นไปไม่ได้ที่จะประกาศตัวแปรชนิดvoidจึงไม่สามารถรับค่าส่งคืนของvoidฟังก์ชันได้แม้จะมีตัวชี้เป็นโมฆะก็ตาม

void foo(int i) { return; }

int main(void) {
  void *j;
  j = foo(0);

  return 0;
}
main.c:5:5: error: assigning to 'void *' from
      incompatible type 'void'
  j = foo(0);
    ^ ~~~~~~

พิมพ์ดีดvoid *เป็นกรณีอื่น ตัวชี้โมฆะบ่งชี้ตัวชี้ไปยังตำแหน่งในหน่วยความจำ แต่ไม่ได้ระบุชนิดของข้อมูลที่ตัวชี้นั้น (นี่คือการใช้เพื่อให้เกิดความหลากหลายใน Cเช่นกับฟังก์ชั่น qsort () ) พอยน์เตอร์เหล่านี้สามารถใช้งานได้ยากเนื่องจากเป็นเรื่องง่ายที่จะโยนมันผิดประเภท โค้ดด้านล่างจะไม่ส่งข้อผิดพลาดของคอมไพเลอร์Cแต่จะส่งผลให้เกิดพฤติกรรมที่ไม่ได้กำหนด:

#include <stdio.h>

int main(void) {
  double foo = 47.2;    //create a double
  void *bar = &foo;     //create a void pointer to that double
  char *baz = bar;      //create a char pointer from the void pointer, which
                        //is supposed to hold a double

  fprintf(stdout, "%s\n", baz);
}

อย่างไรก็ตามรหัสต่อไปนี้ถูกกฎหมายอย่างสมบูรณ์ การส่งไปยังและจากตัวชี้โมฆะจะไม่เปลี่ยนค่าที่เก็บไว้

#include <stdio.h>

int main(void) {
  double foo = 47.2;
  void *bar = &foo;
  double *baz = bar;

  fprintf(stdout, "%f\n", *baz);
}

47.200000

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

int quux(void *);   //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int);    //a function that receives an int, and returns a pointer to data whose type is not known.

tl; dr voidในฟังก์ชั่นต้นแบบหมายถึง "ไม่มีข้อมูล" และระบุว่าไม่มีค่าส่งคืนหรือไม่มีพารามิเตอร์void *ในต้นแบบฟังก์ชั่นหมายถึง "ข้อมูลที่ตัวชี้ฟังก์ชั่นนี้จะได้รับไม่มีประเภทที่รู้จัก" และระบุพารามิเตอร์หรือค่าตอบแทน ซึ่งตัวชี้ต้องถูกส่งไปยังชนิดที่แตกต่างกันก่อนที่จะสามารถใช้ข้อมูลที่ตัวชี้ได้


void * ... must be cast to another type first, but may be done so without an explicit cast.ไม่เป็นความจริงใน C ++ ใน C ++ แบบฟอร์มการแปลงvoid*จะต้องชัดเจน PS ที่เรียกการร่ายที่ชัดเจนนั้นซ้ำซ้อนเนื่องจากการร่ายเป็นโดยการแปลงที่ชัดเจน
eerorika

อัปเดตเพื่อสะท้อนความแตกต่างของ C / C ++ ขอขอบคุณที่แจ้งให้เราทราบ!
Nick Reed

4

foo(void) - ฟังก์ชั่นโดยไม่มีพารามิเตอร์

foo(void *)- ฟังก์ชั่นที่มีหนึ่งvoid *พารามิเตอร์

คือvoid *อะไร มันเป็นเพียงตัวชี้ไปยังข้อมูลที่ไม่มีประเภทที่ระบุ มันสามารถใช้กับพอยน์เตอร์ชนิดอื่น ๆ ได้

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}

คำตอบที่จำเป็นดังนั้นจึงเป็นคำตอบที่ดีที่สุด ฉันแค่อยากจะด่าว่านี่เป็นข้อยกเว้นใน(type) vs. (type *)จักรวาลคู่เพราะความว่างเปล่าไม่ใช่ประเภทจริง
Roberto Caboni

2

ฟังก์ชั่นและการพูด syntactically มีความแตกต่างระหว่างฟังก์ชั่นที่มีต้นแบบเป็น int foo (void) และ int foo (void *)?

มีความแตกต่าง:

int foo(void) ประกาศฟังก์ชั่นที่ไม่ยอมรับข้อโต้แย้ง

int foo(void *)ประกาศฟังก์ชั่นที่ยอมรับอาร์กิวเมนต์ชนิดvoid*เดียว

ใน C ++, เปรียบเสมือนการint foo(void)int foo()

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