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


12

ฉันเพิ่งเริ่มเรียนรู้การเขียนโปรแกรมใน C และเพื่อปรับปรุงความเข้าใจของฉันเกี่ยวกับพอยน์เตอร์และอาร์เรย์ฉันพยายามอ้างถึงองค์ประกอบของอาร์เรย์โดยไม่สร้างตัวชี้ใด ๆ เลย:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

รหัสทั้งหมดรวบรวมและทำงานอย่างไม่มีที่ติ

ฉันคิดว่าต้องสร้างตัวชี้สำหรับทุก ๆ อาร์เรย์ในซอร์สโค้ดขนาดใหญ่ดูเหมือนว่าจะไม่มีประสิทธิภาพสูง

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


การใช้printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));จะหลีกเลี่ยงตัวชี้ทางคณิตศาสตร์และเข้าใจได้ง่ายขึ้น
Kasper van den Berg

1
ฮ่าฮ่าคุณเข้าใจฉันแล้ว ฉันทำเช่นนั้นเป็นการทดลองเพื่อให้เข้าใจถึงวิธีการทำงานของพอยน์เตอร์และอาร์เรย์
Niko Gambt

เลขคณิตตัวชี้จริงเร็วกว่าการใช้ดัชนีอาร์เรย์ประมาณ 30%
Andy

คำตอบ:


16

เป็น "ไม่ดี" เท่าที่อ่านได้น้อยเท่านั้น a[x]เป็นสิ่งเดียวกันกับ*(a+x)ดังนั้นจึงไม่มีความแตกต่างในประสิทธิภาพหรือพฤติกรรม (อันที่จริงx[a]จะใช้งานได้) มันเป็นa[x]เรื่องปกติที่มนุษย์เราเข้าใจได้ง่ายกว่ามาก

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

  • *(a+x)= "สิ่งที่ชี้ไปโดยผลรวมของตัวชี้aและเลขจำนวนเต็มx"
  • a[x]= " xสมาชิกลำดับที่ของอาร์เรย์a"

ในทำนองเดียวกันเมื่อคุณต้องการอ้างถึงที่อยู่ขององค์ประกอบอาร์เรย์:

  • (a+x)= "ผลรวมของตัวชี้aและเลขจำนวนเต็มx"
  • &a[x]= "ที่อยู่ของxสมาชิกลำดับที่อาร์เรย์a"

ส่วนใหญ่แล้ว[]เวอร์ชันต่าง ๆ นั้นง่ายต่อการเข้าใจเมื่อคุณกำลังดูโค้ดที่ไม่เกี่ยวกับการใช้งานในหลาย ๆ อาเรย์ (โดยเฉพาะอาเรย์ของอาเรย์) นั่นเป็นสาเหตุที่[]ผู้ปฏิบัติงานมีอยู่ตั้งแต่แรก

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


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

1
@NikoGambt คุณสามารถถามคำถามอื่นได้เสมอ =)
Ixrec

1
คุณหมายถึงอะไรเพียงเท่านี้ ... ? จุดรวมของภาษาการเขียนโปรแกรมคือการทำให้มนุษย์อ่านรหัสได้ง่ายขึ้น ถ้าเราไม่สนใจเรื่องนั้นเราทุกคนจะเขียนรหัส op ด้วยเลขฐานสิบหก
โซโลมอนช้า

2
อาร์เรย์ไม่ใช่พอยน์เตอร์การสลายเพียงแค่พอยน์เตอร์โดยปริยาย
CodesInChaos

4

ใช่มันเป็นการปฏิบัติที่ไม่ดี แต่ไม่ใช่ด้วยเหตุผลที่ไร้ประสิทธิภาพ

ผู้ประกอบการใช้ Arithmetric ตัวชี้ภายใต้ประทุนดังนั้นพวกเขาจึงมีประสิทธิภาพเท่าเทียมกัน

ปัญหาเกี่ยวกับตัวชี้แบบอาร์เมอร์ริคคือมันอ่านผิดได้ง่ายและอ่านยาก

Rule of thumb: อย่าใช้ตัวบ่งชี้ทางคณิตศาสตร์เว้นแต่คุณจะต้อง


1
เนื่องจากมันใช้เลขคณิตของตัวชี้อยู่แล้วนั่นไม่ได้หมายความว่าพอยน์เตอร์จะมีข้อผิดพลาดเหมือนกันและอ่านยาก
Niko Gambt

1
@NikoGambt คอมไพเลอร์ค่อนข้างดีในการทำตัวชี้ทางคณิตศาสตร์ภายใต้ประทุนและไม่ค่อยจะ 'ผิดพลาด'; เป็นโปรแกรมเมอร์ที่จะทำผิดพลาดกับข้อผิดพลาดที่น่ารังเกียจเป็นผล
Kasper van den Berg

@KaspervandenBerg ใช่ฉันเห็นด้วย อย่างไรก็ตามฉันสนใจข้อผิดพลาดที่เกิดจากโปรแกรมเมอร์และฉันก็ไม่แน่ใจนักว่าเป็นวิธีการเขียนโปรแกรมที่ไม่ดีในการทำสิ่งที่ฉันทำที่นั่นในกรณีที่จำเป็นต้องอ้างถึงที่อยู่ของอาเรย์ ถ้ามีกรณีเช่นนี้อยู่
Niko Gambt

1
บางสิ่งบางอย่าง @NikoGambt เขียนที่สามารถอ่านได้น้อยเพื่อวัตถุประสงค์ในการปฏิบัติงานอยู่เกือบตลอดเวลาการปฏิบัติที่ไม่ดี แต่เขียนบางสิ่งบางอย่างที่สามารถอ่านได้น้อยสำหรับการเพิ่มไม่เป็นอย่างแจ่มแจ้งปฏิบัติไม่ดี
Neil

@Neil การทดลองเล็กน้อยของฉันไม่ไร้ประโยชน์ โดยการทำเช่นนั้นฉันได้เรียนรู้ว่าคอมไพเลอร์ดูเหมือนจะสร้างอาเรย์ของพอยน์เตอร์เพื่ออ้างถึงอาเรย์หลายมิติ อย่างไรก็ตามเนื่องจากคุณกล่าวว่าการอ่านได้มีความสำคัญมากกว่าประสิทธิภาพฉันคิดว่ามันยังคงเป็นวิธีการเขียนโปรแกรมที่ไม่ดี
Niko Gambt

0

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

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

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

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

สาวเท้าของเธอคือ x_dim หวังว่าคำตอบของฉันจะชี้แจง!


มันไม่ชัดเจนจาก OP ไม่ว่าจะใช้หรือ คำจำกัดความทั้งสามนี้สามารถใช้กับรหัสใน OP int* array[ROW];int array[ROW][COLUMN];int (*array)[COLUMN];
cmaster - คืนสถานะโมนิกา

ใช่ฉันรู้ว่าคำตอบของฉันค่อนข้างงุ่มง่ามในจุดนั้น ฉันถูกต้องแล้วขอบคุณ!
fhtuft
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.