เป็นโมฆะ * ฟังก์ชั่น () ตัวชี้ไปยังฟังก์ชั่นหรือฟังก์ชั่นกลับเป็นโมฆะ *?


26

void *function()ฉันสับสนเกี่ยวกับความหมายของ
มันเป็นตัวชี้ไปยังฟังก์ชั่นหรือฟังก์ชั่นกลับมาvoid*? ฉันมักจะใช้มันในโครงสร้างข้อมูลเป็นฟังก์ชั่นซ้ำเรียกคืนตัวชี้ แต่เมื่อฉันเห็นรหัสใน multithreading ( pthread) มีการประกาศฟังก์ชั่นเดียวกัน ตอนนี้ฉันสับสนว่าอะไรคือความแตกต่างระหว่างพวกเขา


5
@ goodvibration C สร้างรูปแบบฟรี (และ C ++ "สืบทอด" สิ่งนี้) แม้void*function();ถูกต้องตามหลักไวยากรณ์ เช่นสำหรับ Python พวกเขาเลือกการตัดสินใจที่แตกต่าง - รูปแบบเป็นส่วนหนึ่งของไวยากรณ์ IMHO ทั้งสองมีข้อดีและข้อเสีย
Scheff

3
@ goodvibration ยิ่งคุณพยายามปกป้องโปรแกรมเมอร์จากการทำสิ่งที่พวกเขาต้องการมากขึ้นคุณจะได้รับสิ่งที่ชอบจาวา;)
idclev 463035818

2
@ goodvibration ตัวเลือกน้อยมีความยืดหยุ่นน้อยลง และโปรดจำไว้ว่ามันเป็นทศวรรษที่ผ่านมาเมื่อพวกเขาทำมัน มันง่ายที่จะบ่นหลังจากนั้น ... ;-)
Scheff

2
ในภาษา C ที่void *function()เป็นฟังก์ชั่นการใช้จำนวนข้อของการขัดแย้งและกลับมาคุ้มค่าว่าเมื่อ dereferenced เป็นของประเภทโมฆะ ใน C ++ void* function()เป็นฟังก์ชั่นการขัดแย้งใดและกลับมาเป็นค่าชี้ไปถือเป็นโมฆะ คุณควรตัดสินใจด้วยภาษาที่คุณต้องการ
สตีเฟ่นเมตรเวบบ์

1
@ StephenM.Webb คุณไม่สามารถอ้างสิทธิ์void *ได้ หลังจากที่ทุกคนแม้ว่าคุณจะทำได้สิ่งที่คุณจะทำอย่างไรกับvoid?
Fabio พูดว่า Reinstate Monica

คำตอบ:


38

void *ฟังก์ชั่นที่มีการพิมพ์กลับ

void *function();

ดังนั้นฉันมักจะชอบในกรณีเช่นนี้เพื่อแยกสัญลักษณ์*ออกจากชื่อฟังก์ชันเช่น

void * function();

และตามที่ Jarod42ระบุไว้ในความคิดเห็นคุณสามารถเขียนการประกาศฟังก์ชันใน C ++ อีกครั้งโดยใช้ประเภทการส่งคืนส่วนต่อท้ายเช่น

auto function() -> void *;

หากคุณต้องการประกาศตัวชี้ไปยังฟังก์ชั่นคุณควรเขียน

void ( *function )();

หรือ

void * ( *function )();

หรือตัวชี้ไปยังฟังก์ชันที่ส่งคืนตัวชี้ไปยังฟังก์ชัน

void * ( *( *function )() )();

2
void* function();นั่นเป็นเหตุผลที่ฉันชอบที่จะเขียน นั่นไม่ใช่สิ่งที่ดึงดูด ... ;-) (การแก้ไขเกิดขึ้นในขณะที่เขียนสิ่งนี้)
Scheff

ในรหัสฉันประกาศvoid * reader();แล้วpthread_create(&thread1,null,reader,reader_arg)แทนpthread_create(&thread1,null,&reader,reader_arg)
user9515151

1
@Scheff: หรือแม้กระทั่งauto function() -> void*(C ++) :)
Jarod42

3
หรือตัวชี้ไปยังฟังก์ชันที่ส่งคืนตัวชี้ไปยังฟังก์ชัน นั่นคือสิ่งที่typedefมีไว้สำหรับ ... ;-) #
Andrew Henle

1
@AndrewHenle ด้วย typedef เราไม่มีปัญหา มีปัญหาเกิดขึ้นเมื่อมีการใช้การประกาศโดยไม่มี typedef หรือการประกาศ alias :)
Vlad จากมอสโก

7

เมื่อใดก็ตามที่ฉันไม่แน่ใจเกี่ยวกับปัญหาทางไวยากรณ์ C ฉันชอบที่จะใช้ยูทิลิตี้cdecl ( เวอร์ชั่นออนไลน์ ) เพื่อตีความให้ฉัน มันแปลระหว่างไวยากรณ์ C และภาษาอังกฤษ

ตัวอย่างเช่นฉันใส่ตัวอย่างของคุณvoid *foo()แล้วมันกลับมา

ประกาศ foo เป็นฟังก์ชันส่งคืนตัวชี้เป็นโมฆะ

เพื่อดูว่าไวยากรณ์อื่น ๆ จะมีลักษณะอย่างไรฉันใส่declare foo as pointer to function returning voidและมันกลับมา

โมฆะ (* foo) ()

สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณมี typecasts, star, หรือ brackets หลายระดับในนิพจน์เดียว


2

มันเป็นฟังก์ชั่นคืนตัวชี้ไป voidมันเป็นฟังก์ชั่นการกลับตัวชี้ไปยัง

คิดว่าการประกาศของคุณด้วยวิธีนี้:

void *(function());

นี่จะเป็นฟังก์ชันที่ส่งคืนvoid(หรือไม่มีอะไร):

void (*function2)();

นึกถึงการประกาศข้างต้นด้วยวิธีนี้:

void ((*function2)());

วิธีที่ง่ายกว่ามากในการเขียนสิ่งเหล่านี้คือการใช้typedefs:

typedef void *function_returning_void_pointer();
typedef void function_returning_nothing();

function_returning_void_pointer function;
function_returning_nothing *function2;

โดยทั่วไปจะช่วยลดความสับสนรอบตัวชี้ฟังก์ชั่นและง่ายต่อการอ่าน


0

การประกาศใน C / C ++ อ่านจากตัวบ่งชี้ภายนอกตามตัวดำเนินการที่มีมาก่อนต่อไปนี้ผู้ประกอบการมีความสำคัญ

ดูอย่างรวดเร็วที่ตารางสำคัญประกอบ C / C ++ ในวิกิพีเดียเผยให้เห็นว่าผู้ประกอบการฟังก์ชั่นการโทรมีลำดับความสำคัญสูงกว่าผู้ประกอบการร้าย() *ดังนั้นการประกาศฟังก์ชั่นของคุณจะอ่านดังนี้:

  • เริ่มที่ตัวระบุ: functionคือ

  • function() ฟังก์ชั่นที่ไม่มีข้อโต้แย้ง

  • void* function()void*และผลตอบแทน

หลักการทั่วไปนี้ยังมีประกาศอาร์เรย์ ( []ยังมีความสำคัญสูงกว่า*) และการรวมกันของทั้งสอง ดังนั้น

int *(*arr[42])();

อ่านเป็น

  • arr คือ
  • arr[42] อาร์เรย์ของ 42 องค์ประกอบซึ่ง ได้แก่
  • *arr[42] พอยน์เตอร์ไป
  • (*arr[42])() ฟังก์ชั่นที่ไม่มีข้อโต้แย้งและ
  • int *(*arr[42])()int*กลับ

ใช้เวลาเล็กน้อยในการทำความคุ้นเคยกับสิ่งนี้ แต่เมื่อคุณเข้าใจหลักการแล้วมันง่ายที่จะอ่านคำประกาศเหล่านั้นอย่างไม่น่าสงสัย

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