มีข้อเสียในการผ่าน structs ตามค่าใน C แทนที่จะส่งตัวชี้หรือไม่?
หาก struct มีขนาดใหญ่จะเห็นได้ชัดว่าการดำเนินการด้านการคัดลอกข้อมูลจำนวนมาก แต่สำหรับโครงสร้างที่มีขนาดเล็กก็ควรจะเหมือนกับการส่งผ่านค่าหลายค่าไปยังฟังก์ชัน
มันอาจจะน่าสนใจยิ่งขึ้นเมื่อใช้เป็นค่าตอบแทน C มีค่าส่งคืนเดียวจากฟังก์ชัน แต่บ่อยครั้งที่คุณต้องการหลายค่า ดังนั้นวิธีง่ายๆคือใส่พวกมันไว้ในโครงสร้างและคืนสิ่งนั้น
มีเหตุผลอะไรหรือขัดกับสิ่งนี้?
เนื่องจากอาจไม่ชัดเจนสำหรับทุกคนที่ฉันกำลังพูดถึงที่นี่ฉันจะยกตัวอย่างง่ายๆ
หากคุณกำลังเขียนโปรแกรมใน C คุณจะเริ่มเขียนฟังก์ชันที่มีลักษณะดังนี้:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
นี่ไม่ใช่ปัญหา ปัญหาเดียวคือคุณต้องเห็นด้วยกับเพื่อนร่วมงานของคุณซึ่งลำดับพารามิเตอร์ควรเป็นเช่นนั้นเพื่อให้คุณใช้หลักการเดียวกันในทุกฟังก์ชั่น
แต่จะเกิดอะไรขึ้นเมื่อคุณต้องการส่งคืนข้อมูลประเภทเดียวกัน โดยปกติคุณจะได้รับสิ่งนี้:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
ใช้งานได้ดี แต่มีปัญหามากกว่า ค่าส่งคืนเป็นค่าส่งคืนยกเว้นว่าในการดำเนินการนี้จะไม่ ไม่มีวิธีที่จะบอกได้จากด้านบนว่าฟังก์ชั่น get_data ไม่ได้รับอนุญาตให้ดูสิ่งที่ len ชี้ไป และไม่มีสิ่งใดที่ทำให้คอมไพเลอร์ตรวจสอบว่ามีการส่งคืนค่าจริงผ่านตัวชี้นั้น ดังนั้นเดือนหน้าเมื่อคนอื่นแก้ไขโค้ดโดยไม่เข้าใจอย่างถูกต้อง (เพราะเขาไม่ได้อ่านเอกสารประกอบ) มันจะพังโดยที่ไม่มีใครสังเกตเห็นหรือมันเริ่มทำงานแบบสุ่ม
ดังนั้นทางออกที่ฉันเสนอคือโครงสร้างอย่างง่าย
struct blob { char *ptr; size_t len; }
ตัวอย่างสามารถเขียนใหม่ได้เช่นนี้
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
ด้วยเหตุผลบางอย่างฉันคิดว่าคนส่วนใหญ่จะทำให้ exam_data ใช้ตัวชี้ไปยัง struct blob แต่โดยสัญชาตญาณฉันไม่เห็นสาเหตุ มันยังคงได้พอยน์เตอร์และจำนวนเต็มมันชัดเจนกว่ามากที่พวกมันไปด้วยกัน และในกรณี get_data มันเป็นไปไม่ได้ที่จะทำเลอะเทอะในแบบที่ฉันอธิบายมาก่อนเนื่องจากไม่มีค่าอินพุตสำหรับความยาวและต้องมีความยาวที่ส่งคืน
gettimeofday
) ใช้พอยน์เตอร์แทนและผู้คนก็ใช้มันเป็นตัวอย่าง
void examine data(const struct blob)
ไม่ถูกต้อง