เหตุใดจึงไม่สามารถส่งอาร์เรย์เป็นอาร์กิวเมนต์ของฟังก์ชันใน C


12

ติดตามความคิดเห็นนี้ฉันได้ลอง google ทำไม แต่ google-fu ของฉันล้มเหลว

ความคิดเห็นจากลิงค์:

[... ] แต่สิ่งสำคัญคืออาร์เรย์และพอยน์เตอร์นั้นต่างกันในซี

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

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


ฉันไม่แน่ใจว่ามันเป็นคำตอบ แต่ส่วนหนึ่งของอาร์เรย์คือขนาดของมันดังนั้นฉันเชื่อว่าคุณจะต้องกำหนดฟังก์ชั่นสำหรับทุกขนาดที่คุณต้องการยอมรับ
clcto

คุณหมายถึงเป็นพอยน์เตอร์ของฟังก์ชันหรือไม่ โปรดอธิบายคำถาม
949300

2
@ user949300 ไม่จากบริบทของความคิดเห็นมันค่อนข้างชัดเจน คุณไม่สามารถส่งผ่านอาร์เรย์ไปยังฟังก์ชันได้เนื่องจากมันกลายเป็นตัวชี้และเขาต้องการที่จะรู้ว่าทำไมถึงเป็นเช่นนั้น
Doval

@DocBrown rlemon เสนอการแก้ไขสำหรับสิ่งนี้
Florian Margaine

คำตอบ:


18

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

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

[... } การแก้ปัญหาประกอบด้วยการกระโดดที่สำคัญในห่วงโซ่วิวัฒนาการระหว่าง BCPL ที่ไม่มีตัวตนและการพิมพ์ C มันกำจัดรูปแบบของตัวชี้ในที่เก็บข้อมูลและทำให้เกิดการสร้างตัวชี้เมื่อชื่ออาเรย์ถูกกล่าวถึงในนิพจน์ กฎที่ยังคงอยู่ใน C ของวันนี้คือค่าของประเภทอาเรย์จะถูกแปลงเมื่อปรากฏเป็นนิพจน์ให้เป็นพอยน์เตอร์ของออบเจ็กต์แรกที่สร้างอาเรย์

สิ่งประดิษฐ์นี้เปิดใช้งานรหัส B ที่มีอยู่ส่วนใหญ่เพื่อให้ทำงานได้ต่อไปแม้จะมีการเปลี่ยนแปลงพื้นฐานในความหมายของภาษา [ .. ]


5
struct Foo { int array[N]; } สามารถถูกส่งผ่านโดยค่า และบิตสุดท้ายเกี่ยวกับการจัดการการจัดสรรแบบไดนามิกและแบบคงที่นั้นดูเหมือนว่าคาว (อาร์เรย์ในความหมายที่เข้มงวดที่สุดจะมีขนาดเสมอกันแนวคิดรวบยอดสำหรับสิ่งต่าง ๆ เช่นการทำดัชนีอาร์เรย์เป็นตัวชี้ควบคู่ไปกับการสลายตัวแบบ

@delnan: ฉันคิดว่าหลักการทั่วไปที่ระบุไว้ที่นี่เป็นเสียง เห็นได้ชัดว่าถ้าคุณใส่อาเรย์ของคุณใน struct คุณจะระบุเจตนาของคุณ ในกรณีทั่วไปคุณมักจะผ่านการอ้างอิง
Robert Harvey

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

@RobertHarvey นั่นยังคงเป็นความไม่สมมาตรในระบบ type: ทุกอย่างถูกส่งผ่านตามค่ายกเว้นประเภทอาร์เรย์ (แม้ว่าอาร์เรย์ที่เป็นส่วนหนึ่งของประเภท struct จะถูกส่งผ่านตามค่า) และมันยังใช้สัญกรณ์ที่เหมือนกันทั้งคู่ และในฟังก์ชั่นลายเซ็น)

@delnan: ทำไมจึงมีความเกี่ยวข้องนอกเหนือจากที่คุณต้องจำ
Robert Harvey

9

PDP minicomputer ที่มีหน่วยความจำเพียง 8 kB ไม่สามารถจัดสรรสแต็กขนาดใหญ่มากได้ ดังนั้นในเครื่องดังกล่าวเราต้องระมัดระวังในการออกแบบภาษา (หรือวิวัฒนาการ) เพื่อให้สามารถลดสิ่งที่ต้องใช้ในสแต็กสำหรับการใช้รูทีนย่อยทั่วไปที่คาดไว้ C ยังคงใช้มาจนถึงปัจจุบันเพื่อตั้งโปรแกรมระบบฝังตัวหน่วยความจำที่ จำกัด มาก (ไม่กี่ kB) ดังนั้นการแลกเปลี่ยนจึงเป็นระบบที่ดี

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


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