การรักษาอาร์เรย์ของ C นั้นแตกต่างจาก Java อย่างมากและคุณจะต้องปรับความคิดของคุณให้เหมาะสม อาร์เรย์ใน C ไม่ใช่วัตถุชั้นหนึ่ง (นั่นคือนิพจน์อาร์เรย์ไม่ได้เก็บรักษาว่าเป็น "array-ness" ในบริบทส่วนใหญ่) ใน C การแสดงออกของประเภท "อาร์เรย์ N องค์ประกอบของT
" จะถูกแปลงโดยปริยาย ("การสลายตัว") เพื่อการแสดงออกของประเภท "ตัวชี้ไปที่T
" ยกเว้นเมื่อการแสดงออกอาร์เรย์เป็นตัวถูกดำเนินการของsizeof
หรือ&
ผู้ประกอบการเอกหรือ การแสดงออกของอาร์เรย์เป็นตัวอักษรสตริงที่ใช้ในการเริ่มต้นอาร์เรย์อื่นในการประกาศ
เหนือสิ่งอื่นใดที่นี้หมายถึงว่าคุณไม่สามารถผ่านการแสดงออกอาร์เรย์ฟังก์ชั่นและมีมันได้รับเป็นประเภทอาร์เรย์ ; ฟังก์ชั่นจริงได้รับประเภทตัวชี้:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
ในการเรียกร้องให้foo
แสดงออกstr
ถูกแปลงจากประเภทchar [6]
การchar *
ซึ่งเป็นเหตุผลที่พารามิเตอร์แรกของfoo
การประกาศแทนchar *a
char a[6]
ในsizeof str
เนื่องจากนิพจน์อาร์เรย์เป็นตัวถูกดำเนินการของตัวsizeof
ดำเนินการจึงไม่ถูกแปลงเป็นชนิดตัวชี้ดังนั้นคุณจะได้รับจำนวนไบต์ในอาร์เรย์ (6)
หากคุณสนใจจริงๆคุณสามารถอ่าน Dennis Ritchie's The Development of the C Languageเพื่อทำความเข้าใจว่าการรักษานี้มาจากไหน
ผลที่สุดคือฟังก์ชั่นไม่สามารถคืนค่าประเภทอาเรย์ซึ่งใช้ได้เนื่องจากการแสดงออกของอาเรย์ไม่สามารถเป็นเป้าหมายของการกำหนดได้เช่นกัน
วิธีที่ปลอดภัยที่สุดสำหรับผู้โทรเพื่อกำหนดอาร์เรย์และส่งที่อยู่และขนาดไปยังฟังก์ชันที่ควรจะเขียน:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
อีกวิธีคือฟังก์ชั่นในการจัดสรรอาเรย์แบบไดนามิกและส่งกลับตัวชี้และขนาด:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
ในกรณีนี้ผู้เรียกมีหน้าที่ยกเลิกการจัดสรรอาร์เรย์ด้วยfree
ฟังก์ชันไลบรารี
โปรดทราบว่าdst
ในโค้ดข้างต้นเป็นตัวชี้ง่ายที่จะไม่ได้เป็นตัวชี้ไปยังอาร์เรย์ของchar
char
ตัวชี้และซีแมนทิกส์อาร์เรย์ของ C เป็นเช่นนั้นซึ่งคุณสามารถใช้ตัวดำเนินการตัวห้อย[]
กับนิพจน์ของชนิดอาร์เรย์หรือชนิดตัวชี้ ทั้งสองsrc[i]
และdst[i]
จะเข้าถึงi
องค์ประกอบ 'ของอาร์เรย์ (แม้ว่าจะsrc
มีเฉพาะประเภทอาร์เรย์)
คุณสามารถประกาศตัวชี้ไปยังอาร์เรย์ขององค์ประกอบ N T
และทำสิ่งที่คล้ายกัน:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
ข้อเสียหลายประการข้างต้น ประการแรกรุ่นเก่าของ C คาดว่าSOME_SIZE
จะมีค่าคงที่เวลารวบรวมซึ่งหมายความว่าฟังก์ชั่นจะทำงานกับขนาดอาร์เรย์ได้เพียงครั้งเดียว ประการที่สองคุณจะต้องตรวจสอบตัวชี้อีกครั้งก่อนที่จะใช้ตัวห้อยซึ่งจะตัดโค้ด ตัวชี้ไปยังอาร์เรย์ทำงานได้ดีขึ้นเมื่อคุณจัดการกับอาร์เรย์หลายมิติ