พฤติกรรมที่คุณพบนั้นแท้จริงแล้วเป็นหูดขนาดใหญ่ในภาษาซี เมื่อใดก็ตามที่คุณประกาศฟังก์ชันที่รับพารามิเตอร์อาร์เรย์คอมไพลเลอร์จะไม่สนใจคุณและเปลี่ยนพารามิเตอร์เป็นตัวชี้ ดังนั้นการประกาศเหล่านี้จึงมีพฤติกรรมเหมือนข้อแรก:
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)
a จะเป็นตัวชี้ไปที่ int ในทั้งสี่กรณี หากคุณส่งอาร์เรย์ไปยัง func มันจะสลายตัวเป็นตัวชี้ไปยังองค์ประกอบแรกทันที (ในระบบ 64 บิตตัวชี้ 64 บิตมีขนาดใหญ่เป็นสองเท่าของ int 32 บิตดังนั้นอัตราส่วนขนาดของคุณจะส่งกลับ 2)
จุดประสงค์เดียวของกฎนี้คือการรักษาความเข้ากันได้ย้อนหลังกับคอมไพเลอร์ในอดีตที่ไม่สนับสนุนการส่งผ่านค่าการรวมเป็นอาร์กิวเมนต์ของฟังก์ชัน
นี่ไม่ได้หมายความว่าจะไม่สามารถส่งอาร์เรย์ไปยังฟังก์ชันได้ คุณสามารถหลีกเลี่ยงหูดนี้ได้โดยการฝังอาร์เรย์ลงในโครงสร้าง (นี่คือจุดประสงค์ของ std :: array ของ C ++ 11):
struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0])); /* prints 5 */
}
หรือโดยการส่งตัวชี้ไปยังอาร์เรย์:
void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */
}
ในกรณีที่ขนาดอาร์เรย์ไม่ใช่ค่าคงที่เวลาคอมไพล์คุณสามารถใช้เทคนิคตัวชี้ไปยังอาร์เรย์กับอาร์เรย์ที่มีความยาวตัวแปร C99:
void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */
}