นี่คือสิ่งที่ฉันทำ:
การพัฒนาภาษาซีนำเสนอข้อมูลเชิงลึกเกี่ยวกับวิวัฒนาการของประเภทอาร์เรย์ใน C:
ฉันจะพยายามร่างสิ่งอาร์เรย์:
บรรพบุรุษของ C B และ BCPL ไม่มีประเภทอาร์เรย์ที่แตกต่างกันการประกาศเช่น:
auto V[10] (B)
or
let V = vec 10 (BCPL)
จะประกาศให้ V เป็นตัวชี้ (ไม่ได้พิมพ์) ซึ่งเริ่มต้นให้ชี้ไปยังส่วนที่ไม่ได้ใช้ของหน่วยความจำ 10 "คำ" B ใช้แล้ว*
สำหรับการอ้างอิงตัวชี้และมี[]
สัญกรณ์แบบมือสั้น*(V+i)
หมายถึงV[i]
เช่นเดียวกับใน C / C ++ ในปัจจุบัน อย่างไรก็ตามV
ไม่ใช่อาร์เรย์ แต่ยังคงเป็นตัวชี้ที่ต้องชี้ไปที่หน่วยความจำบางส่วน สิ่งนี้ทำให้เกิดปัญหาเมื่อ Dennis Ritchie พยายามขยาย B ด้วยประเภทของโครงสร้าง เขาต้องการให้อาร์เรย์เป็นส่วนหนึ่งของโครงสร้างเช่นใน C วันนี้:
struct {
int inumber;
char name[14];
};
แต่ด้วยแนวคิด B, BCPL ของอาร์เรย์เป็นตัวชี้สิ่งนี้จะต้องให้name
ฟิลด์มีตัวชี้ที่ต้องเริ่มต้นเมื่อรันไทม์เป็นพื้นที่หน่วยความจำ 14 ไบต์ภายในโครงสร้าง ในที่สุดปัญหาการกำหนดค่าเริ่มต้น / เค้าโครงได้รับการแก้ไขโดยการให้การดูแลเป็นพิเศษกับอาร์เรย์: คอมไพเลอร์จะติดตามตำแหน่งของอาร์เรย์ในโครงสร้างบนสแต็ก ฯลฯ โดยไม่ต้องใช้ตัวชี้ไปยังข้อมูลเพื่อให้เป็นจริงยกเว้นในนิพจน์ที่เกี่ยวข้องกับอาร์เรย์ การรักษานี้ได้รับอนุญาตเกือบรหัส B ทั้งหมดเรียกใช้และยังคงเป็นแหล่งที่มาของ"อาร์เรย์แปลงเป็นตัวชี้ถ้าคุณมองไปที่พวกเขา"กฎ เป็นการแฮ็คที่เข้ากันได้ซึ่งกลายเป็นประโยชน์อย่างมากเนื่องจากอนุญาตให้มีอาร์เรย์ขนาดเปิด
และนี่คือการเดาของฉันว่าทำไมไม่สามารถกำหนดอาร์เรย์ได้: เนื่องจากอาร์เรย์เป็นพอยน์เตอร์ใน B คุณสามารถเขียน:
auto V[10];
V=V+5;
เพื่อสร้าง "อาร์เรย์" ใหม่ ตอนนี้มันไร้ความหมายเพราะฐานของตัวแปรอาร์เรย์ไม่ใช่ค่า lvalue อีกต่อไป ดังนั้นการมอบหมายนี้จึงไม่ได้รับอนุญาตซึ่งช่วยในการตรวจจับโปรแกรมไม่กี่โปรแกรมที่ทำการ rebasing นี้ในอาร์เรย์ที่ประกาศ. แล้วความคิดนี้ก็ติดอยู่: เนื่องจากอาร์เรย์ไม่เคยถูกออกแบบมาให้เป็นชั้นหนึ่งของระบบประเภท C พวกมันจึงถูกมองว่าเป็นสัตว์ร้ายพิเศษซึ่งจะกลายเป็นตัวชี้หากคุณใช้ และจากมุมมองหนึ่ง (ซึ่งไม่สนใจว่า C-arrays เป็นการแฮ็กที่ไม่สมบูรณ์) การไม่อนุญาตการกำหนดอาร์เรย์ยังคงสมเหตุสมผล: อาร์เรย์เปิดหรือพารามิเตอร์ฟังก์ชันอาร์เรย์จะถือว่าเป็นตัวชี้ที่ไม่มีข้อมูลขนาด คอมไพลเลอร์ไม่มีข้อมูลในการสร้างการกำหนดอาร์เรย์สำหรับพวกเขาและจำเป็นต้องมีการกำหนดตัวชี้ด้วยเหตุผลด้านความเข้ากันได้
typedef int vec[3];
void f(vec a, vec b)
{
vec x,y;
a=b;
x=y;
a=x;
x=a;
}
สิ่งนี้ไม่เปลี่ยนแปลงเมื่อมีการแก้ไข C ในปี 1978 เพิ่มการกำหนดโครงสร้าง ( http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf ) แม้ว่าระเบียนจะเป็นประเภทที่แตกต่างกันใน C แต่ก็ไม่สามารถกำหนดได้ในช่วงต้น K&R C คุณต้องคัดลอกแบบสมาชิกที่ชาญฉลาดด้วย memcpy และคุณสามารถส่งเฉพาะพอยน์เตอร์ไปให้เป็นพารามิเตอร์ฟังก์ชันได้ การกำหนด (และการส่งผ่านพารามิเตอร์) ถูกกำหนดให้เป็น memcpy ของหน่วยความจำดิบของโครงสร้างและเนื่องจากสิ่งนี้ไม่สามารถทำลายโค้ดที่มีอยู่ได้จึงถูกนำมาใช้อย่างง่ายดาย ในฐานะที่เป็นผลข้างเคียงที่ไม่ได้ตั้งใจสิ่งนี้ได้นำเสนอการกำหนดอาร์เรย์บางประเภทโดยปริยาย แต่สิ่งนี้เกิดขึ้นที่ไหนสักแห่งภายในโครงสร้างดังนั้นจึงไม่สามารถทำให้เกิดปัญหากับวิธีการใช้อาร์เรย์