ทำไมการจัดทำดัชนีเริ่มต้นที่ศูนย์ใน 'C'


154

ทำไมการจัดทำดัชนีในอาร์เรย์เริ่มต้นด้วยศูนย์ใน C และไม่ใช่ด้วย 1


7
ทุกอย่างเกี่ยวกับพอยน์เตอร์!
medopal

3
เป็นไปได้ซ้ำของDefend zero-based arrays
dmckee --- ผู้ดูแลอดีต kitten

3
ตัวชี้ (อาเรย์) เป็นทิศทางหน่วยความจำและดัชนีเป็นออฟเซ็ตของทิศทางหน่วยความจำนั้นดังนั้นองค์ประกอบแรกของตัวชี้ (อาเรย์) คือผู้ที่ชดเชยเท่ากับ 0
D33pN16h7

3
@drhirsch เพราะเมื่อเรานับชุดของวัตถุเราเริ่มต้นด้วยการชี้ไปที่วัตถุและพูดว่า "หนึ่ง"
phoog

1
คนอเมริกันนับชั้น (อาคาร) ของอาคารจากที่หนึ่งบนพื้น การนับของอังกฤษจากศูนย์ (ชั้นล่าง) เลื่อนขึ้นไปที่ชั้นแรกจากนั้นชั้นสอง ฯลฯ
Jonathan Leffler

คำตอบ:


116

ใน C ชื่อของอาเรย์เป็นตัวชี้[แต่เห็นความคิดเห็น]อ้างอิงถึงตำแหน่งหน่วยความจำและการแสดงออกarray[n]หมายถึงnองค์ประกอบตำแหน่งหน่วยความจำห่างจากองค์ประกอบเริ่มต้น ซึ่งหมายความว่าดัชนีถูกใช้เป็นออฟเซ็ต องค์ประกอบแรกของอาร์เรย์ที่มีอยู่ตรงที่ตั้งของหน่วยความจำที่อาร์เรย์หมาย (0 องค์ประกอบออกไป) array[0]ดังนั้นจึงควรจะแสดงเป็น

สำหรับข้อมูลเพิ่มเติม:

http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html


20
ชื่อของอาร์เรย์คือชื่อของอาร์เรย์ ตรงกันข้ามกับความเข้าใจผิดทั่วไปอาร์เรย์ไม่ได้ชี้ไปในแง่ใด นิพจน์อาร์เรย์ (เช่นชื่อของวัตถุอาร์เรย์) มักจะแปลงเป็นตัวชี้ไปยังองค์ประกอบแรกแต่ไม่เสมอไป ตัวอย่าง: sizeof arrทำให้ขนาดของวัตถุอาร์เรย์ไม่ใช่ขนาดของตัวชี้
Keith Thompson

ในขณะที่คุณเห็นได้ชัดว่าไม่ได้ตอบสนองต่อความคิดเห็นของ @ KeithThompson ฉันต้องการให้คุณใช้หลักสูตรที่มีความผิดมากกว่านี้: " ใน C ชื่อของอาเรย์นั้นเป็นตัวชี้เป็นหลักโดยอ้างอิงจากตำแหน่งหน่วยความจำ " - ไม่ไม่ใช่ . อย่างน้อยไม่ได้อยู่ในมุมมองทั่วไป ในขณะที่คำตอบของคุณสมบูรณ์แบบตอบคำถามในลักษณะที่ 0 เป็นดัชนีเริ่มมีความสำคัญประโยคแรกไม่ถูกต้องธรรมดา อาร์เรย์จะไม่สลายตัวไปยังตัวชี้ไปยังองค์ประกอบแรกเสมอ
RobertS สนับสนุน Monica Cellio

อ้างจากมาตรฐาน C, (C18), 6.3.2.1/4: " ยกเว้นเมื่อมันเป็นตัวถูกดำเนินการของsizeofผู้ประกอบการหรือ&ผู้ประกอบการเอกหรือเป็นตัวอักษรสตริงที่ใช้ในการเริ่มต้นอาร์เรย์การแสดงออกที่มีประเภท" อาร์เรย์ ของ type "ถูกแปลงเป็นนิพจน์ที่มีประเภท" pointer to type "ที่ชี้ไปที่องค์ประกอบเริ่มต้นของวัตถุอาร์เรย์และไม่ใช่ lvalue หากวัตถุอาร์เรย์มีคลาสหน่วยเก็บข้อมูลลงทะเบียนพฤติกรรมจะไม่ได้กำหนด "
RobertS รองรับ Monica Cellio

การสลายตัวนี้เกิดขึ้นในลักษณะ "โดยนัย" หรือ "เป็นทางการ" มากกว่าที่แนะนำไว้ที่นี่ ไม่มีการเสื่อมสภาพไปยังวัตถุตัวชี้ในหน่วยความจำที่เกี่ยวข้อง นี่คือวัตถุของคำถามนี้: อาร์เรย์เปลี่ยนเป็นพอยน์เตอร์ของตัวชี้เปลี่ยนเป็นวัตถุตัวชี้หรือไม่? - โปรดแก้ไขคำตอบของคุณให้ถูกต้องครบถ้วน
RobertS สนับสนุน Monica Cellio

103

คำถามนี้ถูกโพสต์เมื่อปีที่แล้ว แต่นี่จะไป ...


เกี่ยวกับเหตุผลข้างต้น

ในขณะที่บทความของ Dijkstra (อ้างอิงก่อนหน้านี้ในคำตอบที่ถูกลบตอนนี้) ทำให้รู้สึกจากมุมมองทางคณิตศาสตร์มันไม่เกี่ยวข้องเมื่อมันมาถึงการเขียนโปรแกรม

การตัดสินใจที่ทำโดยข้อกำหนดภาษา & นักออกแบบคอมไพเลอร์ขึ้นอยู่กับการตัดสินใจของนักออกแบบระบบคอมพิวเตอร์ที่จะเริ่มนับที่ 0


เหตุผลที่น่าจะเป็น

อ้างจากข้ออ้างเพื่อสันติภาพโดย Danny Cohen

สำหรับฐาน b ใด ๆ เป็นลำดับแรก b ^ N จำนวนเต็มที่ไม่เป็นลบแรกจะถูกแทนด้วยตัวเลขNแน่นอน(รวมถึงศูนย์นำหน้า) เฉพาะเมื่อการกำหนดหมายเลขเริ่มต้นที่ 0

สามารถทดสอบได้ค่อนข้างง่าย ใน base-2 ใช้2^3 = 8 หมายเลข 8 คือ:

  • 8 (ไบนารี: 1,000) ถ้าเราเริ่มนับที่ 1
  • 7 (ไบนารี: 111) ถ้าเราเริ่มนับที่ 0

111 สามารถแสดงโดยใช้ 3บิตในขณะที่1000จะต้องมีบิตพิเศษ (4 บิต)


ทำไมเรื่องนี้ถึงเกี่ยวข้องกัน

ที่อยู่หน่วยความจำของคอมพิวเตอร์มี2^Nเซลล์ที่Nบิต ตอนนี้ถ้าเราเริ่มนับที่ 1 2^Nเซลล์จะต้องมีN+1บรรทัดที่อยู่ จำเป็นต้องใช้บิตพิเศษเพื่อเข้าถึงที่อยู่ 1 ที่แน่นอน (1000ในกรณีข้างต้น) อีกวิธีในการแก้ปัญหาคือปล่อยให้ที่อยู่สุดท้ายไม่สามารถเข้าถึงได้และใช้Nบรรทัดที่อยู่

ทั้งคู่เป็นวิธีแก้ปัญหาย่อยที่ดีที่สุดเมื่อเทียบกับจำนวนเริ่มต้นที่ 0 ซึ่งจะทำให้ที่อยู่ทั้งหมดสามารถเข้าถึงได้โดยใช้Nบรรทัดที่อยู่!


ข้อสรุป

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


ข้อความจากกระดาษ:

ป้อนคำอธิบายรูปภาพที่นี่


2
เกิดอะไรขึ้นถ้าพวกเขาเพิ่งลบบิต 0 .. ดังนั้นจำนวนที่ 8 จะยังคงเป็น 111 ...
DanMatlin

2
คุณแนะนำให้ทำการดัดแปลงเลขคณิตพื้นฐานเพื่อให้เหมาะสมหรือไม่? คุณไม่คิดว่าสิ่งที่เรามีในวันนี้เป็นทางออกที่ดีกว่าหรือ
Anirudh Ramanathan

หลายปีต่อมา 2 cnt ของฉันมีค่า จากประสบการณ์ของฉัน (ประมาณ 35 ปีแห่งการเขียนโปรแกรม) การทำงานแบบโมดูโลหรือโมดูลาร์เพิ่มเติมในรูปแบบเดียวหรืออื่น ๆ มักจะเกิดขึ้นอย่างน่าประหลาดใจ ด้วยศูนย์ฐานลำดับต่อไปคือ (i + 1)% n แต่ด้วย base 1 มันมา (i-1)% n) +1 ดังนั้นฉันคิดว่า 0 ควรเป็นที่ต้องการ พืชนี้ขึ้นในวิชาคณิตศาสตร์และการเขียนโปรแกรมค่อนข้างบ่อย อาจเป็นแค่ฉันหรือสาขาที่ฉันทำงาน
nyholku

ในขณะที่เหตุผลที่ดีทั้งหมดฉันคิดว่ามันง่ายกว่ามาก: a[b]มีการใช้งานเหมือน*(a+b)ในคอมไพเลอร์ยุคแรก แม้วันนี้คุณยังสามารถเขียนแทน2[a] a[2]ตอนนี้ถ้าดัชนีไม่ได้เริ่มต้นที่ 0 แล้วจะกลายเป็นa[b] *(a+b-1)สิ่งนี้จะต้องเพิ่ม 2 ครั้งบน CPUs แทน 0 ซึ่งหมายถึงความเร็วครึ่งหนึ่ง เห็นได้ชัดว่าไม่ต้องการ
Goswin von Brederlow

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

27

เนื่องจาก 0 คือระยะห่างจากตัวชี้ไปยังส่วนหัวของอาร์เรย์จนถึงองค์ประกอบแรกของอาร์เรย์

พิจารณา:

int foo[5] = {1,2,3,4,5};

ในการเข้าถึง 0 เราทำได้:

foo[0] 

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

*(foo + 0)

เลขคณิตตัวชี้วันนี้ไม่ได้ถูกใช้บ่อยนัก ย้อนกลับไปแม้ว่ามันเป็นวิธีที่สะดวกในการระบุที่อยู่และย้าย X "ints" ออกจากจุดเริ่มต้นนั้น แน่นอนถ้าคุณต้องการอยู่ในที่ที่คุณอยู่คุณก็แค่เพิ่ม 0!


23

เนื่องจากดัชนีที่ใช้ 0 อนุญาตให้ ...

array[index]

... ที่จะดำเนินการเป็น ...

*(array + index)

หากดัชนีเป็นแบบ 1 คอมไพเลอร์จะต้องสร้าง: *(array + index - 1)และ "-1" นี้จะทำให้ประสิทธิภาพเสียหาย


4
คุณนำจุดที่น่าสนใจขึ้นมา มันสามารถทำร้ายประสิทธิภาพ แต่ประสิทธิภาพในการทำงานจะมีนัยสำคัญที่จะแสดงให้เห็นถึงการใช้ 0 เป็นดัชนีเริ่มต้นหรือไม่ ฉันสงสัยมัน.
FirstName นามสกุล

3
@FirstNameLastName ดัชนีที่ใช้ 1 เสนอไม่ได้เปรียบกว่าดัชนีตาม 0 แต่พวกเขาดำเนินการ (เล็กน้อย) แย่ลง นั่นเป็นการปรับดัชนีตาม 0 ไม่ว่ากำไรนั้น "เล็ก" จะเป็นอย่างไร แม้ว่าดัชนีที่อิงกับ 1 จะมีข้อได้เปรียบ แต่ก็อยู่ในจิตวิญญาณของ C ++ ที่จะเลือกประสิทธิภาพเหนือความสะดวกสบาย C ++ บางครั้งใช้ในบริบทที่ทุก ๆ บิตของประสิทธิภาพมีความสำคัญและสิ่งที่ "เล็ก" เหล่านี้สามารถเพิ่มได้อย่างรวดเร็ว
Branko Dimitrijevic

ใช่ฉันเข้าใจว่าสิ่งเล็ก ๆ น้อย ๆ สามารถรวมกันและบางครั้งก็กลายเป็นเรื่องใหญ่ ตัวอย่างเช่น $ 1 ต่อปีไม่ใช่เงินมาก แต่ถ้ามีคนบริจาค 2 พันล้านคนเราก็สามารถทำสิ่งดีๆเพื่อมนุษยชาติได้มากมาย ฉันกำลังมองหาตัวอย่างที่คล้ายกันในการเข้ารหัสซึ่งอาจทำให้ประสิทธิภาพต่ำ
FirstName นามสกุล

2
แทนที่จะลบ 1 คุณควรใช้ที่อยู่ของอาร์เรย์ 1 เป็นที่อยู่พื้นฐาน นั่นคือสิ่งที่เราทำในคอมไพเลอร์ที่ฉันเคยทำ ที่กำจัดการลบรันไทม์ เมื่อคุณเขียนคอมไพเลอร์คำแนะนำพิเศษเหล่านั้นมีความสำคัญมาก คอมไพเลอร์จะถูกใช้เพื่อสร้างโปรแกรมหลายพันโปรแกรมโดยแต่ละโปรแกรมสามารถใช้งานได้หลายพันครั้งและคำสั่งพิเศษ 1 รายการอาจเกิดขึ้นในหลาย ๆ บรรทัดภายในวงวน n กำลังสอง มันสามารถเพิ่มรอบการสูญเปล่านับพันล้าน
progrmr

ไม่เคยชินกับประสิทธิภาพเมื่อคอมไพล์แล้วมันจะเพิ่มเวลาสร้างเพียงเล็กน้อยเพราะในท้ายที่สุดมันจะถูกแปลเป็นรหัสเครื่องมันจะทำร้ายนักออกแบบคอมไพเลอร์เท่านั้น
Hassaan Akbar

12

เพราะมันทำให้คอมไพเลอร์และลิงเกอร์ง่ายขึ้น (เขียนง่ายกว่า)

เอกสารอ้างอิง :

"... การอ้างอิงหน่วยความจำตามที่อยู่และออฟเซ็ตถูกแสดงโดยตรงในฮาร์ดแวร์บนแทบทุกสถาปัตยกรรมคอมพิวเตอร์ดังนั้นรายละเอียดการออกแบบใน C ทำให้การรวบรวมง่ายขึ้น"

และ

"... สิ่งนี้ทำให้การติดตั้งง่ายขึ้น ... "


1
+1 ไม่แน่ใจว่าเพราะเหตุใดการลงคะแนน แม้ว่ามันจะไม่ได้ตอบคำถามโดยตรง แต่การทำดัชนีแบบ 0 นั้นไม่ได้เป็นเรื่องธรรมดาสำหรับคนหรือนักคณิตศาสตร์ แต่เหตุผลเดียวที่ทำคือเพราะการใช้งานนั้นมีความสอดคล้องเชิงตรรกะ (ง่าย)
phkahler

4
@phkahler: ข้อผิดพลาดอยู่ในผู้แต่งและภาษาที่เรียกว่าดัชนีอาร์เรย์เป็นดัชนี ถ้าคุณคิดว่ามันเป็นสิ่งชดเชยแล้วการใช้ 0 กลายเป็นเรื่องธรรมดาสำหรับคนทั่วไปเช่นกัน พิจารณานาฬิกานาทีแรกเขียนเป็น 00:00 ไม่ใช่ 00:01 ใช่ไหม
Lie Ryan

3
+1 - นี่อาจเป็นคำตอบที่ถูกต้องที่สุด C ลงวันที่ก่อนวันจริงของกระดาษ Djikistras และเป็นหนึ่งใน "เริ่มต้นที่ 0" ภาษาแรกสุด C เริ่มต้นชีวิต "เป็นแอสเซมเบลอร์ระดับสูง" และเป็นไปได้ว่า K & R ต้องการที่จะติดอย่างใกล้ชิดกับวิธีที่มันทำในแอสเซมเบลอร์ที่คุณจะมีฐานที่อยู่ปกติ
James Anderson

ฉันคิดว่าคำถามคือทำไมใช้ 0 ตามไม่ดีกว่า
progrmr

2
ฉันจะไม่ downvote แต่เป็นความเห็น progrmr ด้านบนฐานสามารถได้รับการดูแลโดยการปรับที่อยู่อาร์เรย์ดังนั้นโดยไม่คำนึงถึงเวลาดำเนินการฐานเดียวกันและนี่เป็นเรื่องเล็กน้อยที่จะนำไปใช้ในคอมไพเลอร์หรือล่าม . เป็นสักขีพยาน Pascal ที่คุณสามารถใช้ช่วงใด ๆ สำหรับการจัดทำดัชนี IIRC มันเป็นเวลา 25 ปีแล้ว)
nyholku

5

ดัชนีอาร์เรย์เสมอเริ่มต้นด้วย zero.Let ถือว่าอยู่ฐานคือ 2000 arr[i] = *(arr+i)ตอนนี้ ตอนif i= 0นี้หมายถึง*(2000+0) เท่ากับที่อยู่ฐานหรือที่อยู่ขององค์ประกอบแรกในอาร์เรย์ ดัชนีนี้ถือว่าเป็นออฟเซ็ตดังนั้นดัชนี bydeafault เริ่มต้นจากศูนย์


5

ด้วยเหตุผลเดียวกันว่าเมื่อเป็นวันพุธและบางคนถามคุณว่ากี่วันถึงวันพุธคุณจะพูดว่า 0 มากกว่า 1 และเมื่อเป็นวันพุธและบางคนถามคุณว่ากี่วันจนถึงวันพฤหัสบดีคุณจะพูดว่า 1 มากกว่า 2


6
คำตอบของคุณดูเหมือนเป็นเรื่องของความคิดเห็น
heltonbiker

6
มันเป็นสิ่งที่ทำให้การเพิ่มดัชนี / ออฟเซ็ตทำงานได้ ตัวอย่างเช่นถ้า "วันนี้" เป็น 0 และ "วันพรุ่งนี้" คือ 1, "วันพรุ่งนี้วันพรุ่งนี้" คือ 1 + 1 = 2 แต่ถ้า "วันนี้" เป็น 1 และ "พรุ่งนี้" เป็น 2 "พรุ่งนี้คือวันพรุ่งนี้" ไม่ใช่ 2 + 2 ในอาร์เรย์ปรากฏการณ์นี้จะเกิดขึ้นทุกครั้งที่คุณต้องการพิจารณาช่วงย่อยของอาร์เรย์ว่าเป็นอาร์เรย์ที่อยู่ด้านขวา
.. GitHub หยุดช่วยเหลือน้ำแข็ง

7
การเรียกคอลเล็กชั่น 3 สิ่ง "3 สิ่ง" และการกำหนดหมายเลข 1,2,3 ไม่ใช่ข้อบกพร่อง การนับพวกมันด้วยการชดเชยจากอันแรกนั้นไม่เป็นธรรมชาติแม้แต่ในวิชาคณิตศาสตร์ ครั้งเดียวที่คุณทำดัชนีจากศูนย์ในวิชาคณิตศาสตร์คือเมื่อคุณต้องการรวมบางสิ่งบางอย่างเช่นกำลังที่ศูนย์ (เทอมคงที่) ในพหุนาม
phkahler

9
Re: "การกำหนดหมายเลขอาร์เรย์ที่เริ่มต้นด้วย 1 แทนที่จะเป็น 0 สำหรับคนที่มีความบกพร่องทางคณิตศาสตร์อย่างรุนแรง" "ความรู้เบื้องต้นเกี่ยวกับอัลกอริทึม" ของ CLR รุ่นของฉันใช้การจัดทำดัชนีแบบอาเรย์ 1 รายการ; ฉันไม่คิดว่าผู้เขียนมีข้อบกพร่องในการคิดทางคณิตศาสตร์
RexE

ไม่ฉันจะบอกว่าตำแหน่งที่เจ็ดอยู่ที่ดัชนี 6 หรือ 6 ตำแหน่งจากตำแหน่งแรก
.. GitHub หยุดช่วยน้ำแข็ง

2

คำอธิบายที่หรูหราที่สุดที่ฉันได้อ่านสำหรับการกำหนดตัวเลขเป็นศูนย์คือการสังเกตว่าค่าไม่ได้ถูกเก็บไว้ในสถานที่ที่ทำเครื่องหมายไว้บนบรรทัดตัวเลข แต่จะอยู่ในช่องว่างระหว่างพวกเขา รายการแรกจะถูกเก็บไว้ระหว่างศูนย์และหนึ่งรายการถัดไประหว่างหนึ่งและสอง ฯลฯ รายการที่ N จะถูกเก็บไว้ระหว่าง N-1 และ N ช่วงของรายการอาจมีการอธิบายโดยใช้ตัวเลขที่ด้านใดด้านหนึ่ง แต่ละรายการเป็นไปตามแบบแผนที่อธิบายโดยใช้หมายเลขด้านล่าง หากมีการกำหนดช่วง (X, Y) การระบุหมายเลขบุคคลโดยใช้หมายเลขด้านล่างหมายความว่าเราสามารถระบุรายการแรกได้โดยไม่ต้องใช้เลขคณิตใด ๆ (เป็นรายการที่ X) แต่ต้องลบหนึ่งรายการจาก Y เพื่อระบุรายการสุดท้าย (Y -1) การระบุไอเท็มโดยใช้หมายเลขด้านบนจะช่วยให้การระบุรายการสุดท้ายในช่วงนั้นง่ายขึ้น (เป็นรายการ Y)

แม้ว่ามันจะไม่น่ากลัวที่จะระบุไอเท็มตามจำนวนที่อยู่เหนือพวกมัน แต่การกำหนดไอเท็มแรกในช่วง (X, Y) ว่าเป็นไอเท็มหนึ่งข้างต้น X นั้นใช้งานได้ดีกว่าการกำหนดว่าเป็นหนึ่งด้านล่าง (X + 1)


1

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


1

ลองเข้าถึงหน้าจอพิกเซลโดยใช้พิกัด X, Y บนเมทริกซ์ที่ใช้ 1 สูตรมีความซับซ้อนอย่างที่สุด ทำไมมีความซับซ้อน เนื่องจากคุณแปลง X, Y ให้กลายเป็นหนึ่งหมายเลข ทำไมคุณต้องแปลง X, Y เป็นออฟเซ็ต เพราะนั่นคือวิธีที่หน่วยความจำถูกจัดระเบียบภายในคอมพิวเตอร์เช่นเดียวกับกระแสหน่วยความจำเซลล์ (อาร์เรย์) คอมพิวเตอร์เกี่ยวข้องกับเซลล์อาร์เรย์ได้อย่างไร ใช้ offsets (การกระจัดจากเซลล์แรกเป็นรูปแบบการจัดทำดัชนี zero-based)

ดังนั้นในบางจุดของรหัสที่คุณต้องการ (หรือคอมไพเลอร์ต้องการ) เพื่อแปลงสูตร 1 ฐานเป็นสูตรที่ใช้ 0 เพราะนั่นคือวิธีที่คอมพิวเตอร์จัดการกับหน่วยความจำ


1

สมมติว่าเราต้องการสร้างอาร์เรย์ขนาด 5
int array [5] = [2,3,5,9,8]

ให้องค์ประกอบที่ 1 ของอาร์เรย์นั้นชี้ไปที่ตำแหน่ง 100

และให้เราพิจารณาการทำดัชนีเริ่มจาก 1 ไม่ใช่ 0.

ตอนนี้เราต้องค้นหาตำแหน่งขององค์ประกอบที่ 1 ด้วยความช่วยเหลือของดัชนี
(จำตำแหน่งขององค์ประกอบที่ 1 ได้ 100)

เนื่องจากขนาดของจำนวนเต็มคือ 4 บิต
ดังนั้น -> พิจารณาดัชนี 1 ตำแหน่งจะมี
ขนาด ของ index (1) * ขนาดของจำนวนเต็ม (4) = 4
ดังนั้นตำแหน่งจริงที่มันจะแสดงให้เราเห็นคือ

100 + 4 = 104

ซึ่งไม่เป็นความจริงเพราะตำแหน่งเริ่มต้นอยู่ที่ 100
ซึ่งควรชี้ไปที่ 100 ไม่ใช่ที่ 104 ตอนนี้
ผิด

ตอนนี้สมมติว่าเราได้ทำดัชนีจาก 0
แล้ว
ตำแหน่งขององค์ประกอบที่ 1 ควรเป็น
ขนาดของดัชนี (0) * ขนาดของจำนวนเต็ม (4) = 0

ดังนั้น ->
ตำแหน่งขององค์ประกอบที่ 1 คือ 100 + 0 = 100

และนั่นคือตำแหน่งที่แท้จริงขององค์ประกอบ
นี่คือสาเหตุที่การทำดัชนีเริ่มต้นที่ 0;

ฉันหวังว่ามันจะชัดเจนจุดของคุณ


1

ฉันมาจากพื้นหลังของจาวา ฉันได้นำเสนอคำตอบสำหรับคำถามนี้ในแผนภาพด้านล่างซึ่งฉันได้เขียนไว้ในกระดาษซึ่งอธิบายด้วยตนเอง

ขั้นตอนหลัก:

  1. การสร้างการอ้างอิง
  2. การเริ่มต้นอาร์เรย์
  3. การจัดสรรข้อมูลไปยังอาเรย์

  • นอกจากนี้โปรดทราบว่าเมื่ออาเรย์ถูกสร้างอินสแตนซ์แล้ว .... ศูนย์จะจัดสรรให้กับบล็อกทั้งหมดตามค่าเริ่มต้นจนกระทั่งเรากำหนดค่าให้
  • Array เริ่มต้นด้วยศูนย์เนื่องจากที่อยู่แรกจะชี้ไปที่การอ้างอิง (i: e - X102 + 0 in image)

ป้อนคำอธิบายรูปภาพที่นี่

หมายเหตุ : บล็อกที่แสดงในภาพคือการแสดงหน่วยความจำ


0

ก่อนอื่นคุณต้องรู้ว่าอาเรย์นั้นถูกพิจารณาเป็นพอยน์เตอร์ภายในเพราะ "ชื่อของอาเรย์นั้นมีที่อยู่ขององค์ประกอบแรกของอาเรย์"

ex. int arr[2] = {5,4};

พิจารณาว่าอาร์เรย์เริ่มต้นที่ที่อยู่ 100 ดังนั้นองค์ประกอบแรกจะเป็นที่ที่อยู่ 100 และวินาทีจะอยู่ที่ 104 ตอนนี้ให้พิจารณาว่าถ้าดัชนีอาร์เรย์เริ่มต้นจาก 1 ดังนั้น

arr[1]:-

นี้สามารถเขียนในการแสดงออกพอยน์เตอร์เช่นนี้ -

 arr[1] = *(arr + 1 * (size of single element of array));

พิจารณาขนาดของ int คือ 4bytes ตอนนี้

arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);

ดังที่เราทราบชื่ออาร์เรย์มีที่อยู่ขององค์ประกอบแรกดังนั้น arr = 100 ตอนนี้

arr[1] = *(100 + 4);
arr[1] = *(104);

ซึ่งจะช่วยให้,

arr[1] = 4;

เนื่องจากการแสดงออกนี้เราไม่สามารถเข้าถึงองค์ประกอบที่อยู่ 100 ซึ่งเป็นองค์ประกอบแรกอย่างเป็นทางการ

ตอนนี้ให้พิจารณาดัชนีอาเรย์เริ่มจาก 0 ดังนั้น

arr[0]:-

สิ่งนี้จะได้รับการแก้ไขในฐานะ

arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);

ตอนนี้เรารู้ว่าชื่ออาร์เรย์มีที่อยู่ขององค์ประกอบแรกของมันดังนั้น

arr[0] = *(100);

ซึ่งให้ผลลัพธ์ที่ถูกต้อง

arr[0] = 5;

ดังนั้นดัชนีอาเรย์จะเริ่มจาก 0 ในคเสมอ

การอ้างอิง: รายละเอียดทั้งหมดเขียนไว้ในหนังสือ "ภาษาซีโดย brian kerninghan และ dennis ritchie"


0

ในอาร์เรย์ดัชนีจะบอกระยะทางจากองค์ประกอบเริ่มต้น ดังนั้นองค์ประกอบแรกอยู่ที่ 0 ระยะทางจากองค์ประกอบเริ่มต้น นั่นคือสาเหตุที่อาร์เรย์เริ่มต้นจาก 0


0

เป็นเพราะaddressต้องชี้ไปทางขวาelementในอาเรย์ ให้เราสมมติอาร์เรย์ด้านล่าง:

let arr = [10, 20, 40, 60]; 

ให้เราพิจารณาจุดเริ่มต้นของการเป็นที่อยู่12และขนาดของBEelement4 bytes

address of arr[0] = 12 + (0 * 4) => 12
address of arr[1] = 12 + (1 * 4) => 16
address of arr[2] = 12 + (2 * 4) => 20
address of arr[3] = 12 + (3 * 4) => 24

ถ้ามันไม่ได้ zero-basedในทางเทคนิคที่อยู่องค์ประกอบแรกของเราในarrayจะเป็นซึ่งเป็นสิ่งที่ผิดเป็นสถานที่มันเป็น1612


-2

ชื่ออาร์เรย์เป็นตัวชี้ค่าคงที่ที่ชี้ไปยังที่อยู่พื้นฐานเมื่อคุณใช้ arr [i] คอมไพเลอร์จะจัดการมันเป็น * (arr + i) เนื่องจากช่วง int คือ -128 ถึง 127 คอมไพเลอร์คิดว่า -128 ถึง -1 คือ ตัวเลขลบและ 0 ถึง 128 เป็นตัวเลขบวกดังนั้นดัชนีอาร์เรย์จะเริ่มต้นด้วยศูนย์เสมอ


1
'int range คือ -128 to 127'คุณหมายถึงอะไร intจำเป็นต้องมีประเภทเพื่อรองรับช่วงอย่างน้อย 16 บิตและในระบบส่วนใหญ่ในปัจจุบันรองรับ 32 บิต ฉันคิดว่าตรรกะของคุณมีข้อบกพร่องและคำตอบของคุณไม่ได้ปรับปรุงคำตอบอื่น ๆ ที่ได้รับจากคนอื่น ๆ ฉันแนะนำให้ลบสิ่งนี้
Jonathan Leffler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.