ตัวชี้ไปยังตัวชี้ชี้แจง


142

ฉันกำลังทำตามบทช่วยสอนนี้เกี่ยวกับตัวชี้ไปยังตัวชี้ทำงานอย่างไร

ให้ฉันอ้างอิงข้อความที่เกี่ยวข้อง:


    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;

ตอนนี้เราสามารถตั้งค่า

    int **ipp = &ip1;

และippชี้ไปที่จุดที่จะต้องip1 คือและคือหรือ 5 เราสามารถอธิบายสถานการณ์ด้วยสัญกรณ์กล่องและลูกศรที่เราคุ้นเคยเช่นนี้i*ippip1**ippi

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

ถ้าอย่างนั้นเราพูด

    *ipp = ip2;

เราได้เปลี่ยนพอยน์เตอร์ที่ชี้โดยipp(นั่นคือip1) เพื่อให้มีสำเนาip2ดังนั้นip1ตอนนี้( ) จะชี้ไปที่j:

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


คำถามของฉันคือ: ทำไมในภาพที่สองippยังคงชี้ไปip1แต่ไม่ip2?


6
กรุณาเพิ่มประเภทของippเมื่อกำหนดมันดังนั้นคำถามของคุณเสร็จสมบูรณ์ ;-)
zmo

1
เพราะการippชี้ไปที่ip1นั้น*ipp = ip2ก็เหมือนกับip1 = ip2
Grijesh Chauhan

1
เราจะหยุดเขียนเครื่องหมายดอกจันที่อยู่ไกลจากประเภทแหลมได้ไหม? int **ippไกลน้อยกว่าสัญชาตญาณint** ippโดยเฉพาะอย่างยิ่งเมื่อ**ippหมายถึงสิ่งที่แตกต่างอย่างสิ้นเชิงนอกเหนือจากการประกาศประเภท
Darkhogg

4
@Darkhogg int **ippดูเหมือนง่ายสำหรับฉัน มันหมายความว่าฉันทำ อันไหนจริง. **ippint
ithisa

2
@ user54609 หมายและ intuitiveness ส่วนบุคคลออกจากกันพิจารณานี้ประเภทของการippเป็นint**ดังนั้นเพียงแค่เขียนint**แทนขลัง" impdereference เป็น int"เข้าใจ
Manu343726

คำตอบ:


143

ลืมไปสักครู่เกี่ยวกับการเปรียบเทียบการชี้ สิ่งที่ตัวชี้ประกอบด้วยจริงๆคือที่อยู่หน่วยความจำ ตัวดำเนินการ&คือ "ที่อยู่ของ" - นั่นคือส่งคืนที่อยู่ในหน่วยความจำของวัตถุ *ผู้ประกอบการช่วยให้คุณมีวัตถุที่เป็นตัวชี้หมายถึงเช่นกำหนดตัวชี้ที่มีอยู่ก็จะส่งกลับวัตถุที่อยู่หน่วยความจำที่ ดังนั้นเมื่อคุณทำ*ipp = ip2สิ่งที่คุณจะทำคือการ*ippได้รับวัตถุที่อยู่ที่จัดขึ้นในippซึ่งเป็น ip1แล้วกำหนดให้ip1ค่าที่เก็บไว้ในซึ่งเป็นที่อยู่ของip2j

เพียง
& -> ที่อยู่ของ
*-> มูลค่าที่


14
& และ * ไม่เคยง่ายเลย
เรย์

7
ฉันเชื่อว่าแหล่งที่มาหลักของความสับสนนั้นเกิดจากความกำกวมของตัวดำเนินการ * ซึ่งในระหว่างการประกาศตัวแปรใช้เพื่อระบุว่าตัวแปรที่จริงแล้วเป็นตัวชี้ไปยังชนิดข้อมูลบางชนิด แต่ในทางกลับกันมันยังใช้ในคำสั่งเพื่อเข้าถึงเนื้อหาของตัวแปรที่ชี้โดยตัวชี้ (ตัวดำเนินการ dereferencing)
Lucas A.

43

เพราะคุณเปลี่ยนแปลงมูลค่าที่ชี้ไปไม่ได้ค่าของipp ippดังนั้นippยังคงชี้ไปip1(ค่าของipp) ip1's คุ้มค่าในขณะนี้เป็นเช่นเดียวกับip2' ค่า s jเพื่อให้พวกเขาทั้งสองจุด

นี้:

*ipp = ip2;

เหมือนกับ:

ip1 = ip2;

11
อาจมีค่าที่ชี้ให้เห็นความแตกต่างระหว่างint *ip1 = &iและ*ipp = ip2;เช่นถ้าคุณลบออกintจากคำสั่งแรกแล้วการมอบหมายมีลักษณะคล้ายกันมาก แต่การ*ทำสิ่งที่แตกต่างกันมากในทั้งสองกรณี
Crowman

22

เช่นเดียวกับคำถามเริ่มต้นส่วนใหญ่ในแท็ก C คำถามนี้สามารถตอบได้โดยกลับไปที่หลักการแรก:

  • ตัวชี้เป็นค่าชนิดหนึ่ง
  • ตัวแปรมีค่า
  • &ผู้ประกอบการเปลี่ยนตัวแปรเข้าไปในตัวชี้
  • *ผู้ประกอบการหันชี้ลงในตัวแปร

(โดยทางเทคนิคแล้วฉันควรจะพูดว่า "lvalue" แทนที่จะเป็น "variable" แต่ฉันรู้สึกว่ามันชัดเจนกว่าที่จะอธิบายตำแหน่งที่เก็บข้อมูลที่ไม่แน่นอนว่าเป็น "ตัวแปร")

ดังนั้นเราจึงมีตัวแปร:

int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;

ตัวแปรip1 มีตัวชี้ &ผู้ประกอบการจะเปิดเข้าไปในตัวชี้และความคุ้มค่าตัวชี้ที่กำหนดให้i ip1ดังนั้นip1 มีiตัวชี้ไปยัง

ตัวแปรip2 มีตัวชี้ &ผู้ประกอบการจะเปิดเข้าไปในตัวชี้และตัวชี้ที่กำหนดให้j ip2ดังนั้นip2 มีjตัวชี้ไปยัง

int **ipp = &ip1;

ตัวแปรippมีตัวชี้ &ผู้ประกอบการเปลี่ยนตัวแปรเข้าไปในตัวชี้และความคุ้มค่าตัวชี้ที่กำหนดให้ip1 ippดังนั้นมีตัวชี้ไปยังippip1

มาสรุปเรื่องนี้กัน:

  • i มี 5
  • j มี 6
  • ip1มี "ตัวชี้ไปที่i"
  • ip2มี "ตัวชี้ไปที่j"
  • ippมี "ตัวชี้ไปที่ip1"

ตอนนี้เราพูด

*ipp = ip2;

*ผู้ประกอบการหันกลับเข้าไปในตัวชี้ตัวแปร เราเรียกค่าของippซึ่งเป็น "ตัวชี้ไปip1และเปิดเป็นตัวแปร. สิ่งที่ตัวแปร? ip1แน่นอน!

ดังนั้นนี่เป็นอีกวิธีหนึ่งในการพูด

ip1 = ip2;

ip2ดังนั้นเราจึงเรียกค่าของ มันคืออะไร? "ตัวชี้ไปยังj" เรากำหนดค่าตัวชี้ip1นั้นให้ดังนั้นip1ขณะนี้ "ตัวชี้ไปที่j"

เราเปลี่ยนเพียงสิ่งเดียว: ค่าของip1:

  • i มี 5
  • j มี 6
  • ip1มี "ตัวชี้ไปที่j"
  • ip2มี "ตัวชี้ไปที่j"
  • ippมี "ตัวชี้ไปที่ip1"

ทำไมถึงippยังชี้ip1และไม่ip2?

ตัวแปรจะเปลี่ยนแปลงเมื่อคุณกำหนดให้ นับจำนวนที่ได้รับมอบหมาย ไม่สามารถเปลี่ยนแปลงตัวแปรได้มากกว่าที่ได้รับมอบหมาย! คุณเริ่มต้นด้วยการมอบหมายให้i, j, ip1, และip2 ippจากนั้นคุณมอบหมายให้*ippซึ่งตามที่เราเห็นมีความหมายเหมือนกับ "มอบหมายให้ip1" เนื่องจากคุณไม่ได้มอบหมายippเป็นครั้งที่สองจึงไม่เปลี่ยน!

หากคุณต้องการเปลี่ยนแปลงippคุณจะต้องมอบหมายให้ipp:

ipp = &ip2;

เช่น


21

หวังว่ารหัสนี้จะช่วยได้

#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;
    int** ipp = &ip1;
    printf("address of value i: %p\n", &i);
    printf("address of value j: %p\n", &j);
    printf("value ip1: %p\n", ip1);
    printf("value ip2: %p\n", ip2);
    printf("value ipp: %p\n", ipp);
    printf("address value of ipp: %p\n", *ipp);
    printf("value of address value of ipp: %d\n", **ipp);
    *ipp = ip2;
    printf("value ipp: %p\n", ipp);
    printf("address value of ipp: %p\n", *ipp);
    printf("value of address value of ipp: %d\n", **ipp);
}

มันเอาท์พุท:

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


12

ความเห็นส่วนตัวของฉันคือภาพที่มีลูกศรชี้ไปทางนี้หรือทำให้ตัวชี้ยากขึ้นที่จะเข้าใจ มันทำให้พวกมันดูเหมือนสิ่งที่เป็นนามธรรมและลึกลับ พวกเขาจะไม่.

เหมือนทุกสิ่งทุกอย่างในเครื่องคอมพิวเตอร์ของตัวชี้เป็นตัวเลข ชื่อ "ตัวชี้" เป็นเพียงวิธีแฟนซีในการพูดว่า "ตัวแปรที่มีที่อยู่"

ดังนั้นให้ฉันกระตุ้นสิ่งต่าง ๆ โดยอธิบายว่าคอมพิวเตอร์ใช้งานได้จริง

เรามีintมันมีชื่อiและค่า 5 นี้ถูกเก็บไว้ในหน่วยความจำ เช่นเดียวกับทุกสิ่งที่เก็บไว้ในหน่วยความจำต้องมีที่อยู่หรือเราจะไม่สามารถค้นหาได้ ให้บอกว่าiจบลงที่ที่อยู่ 0x12345678 และเพื่อนของมันjด้วยค่า 6 จบลงหลังจากนั้น สมมติว่า CPU แบบ 32 บิตโดยที่ int คือ 4 ไบต์และตัวชี้เป็น 4 ไบต์จากนั้นตัวแปรจะถูกเก็บไว้ในหน่วยความจำกายภาพเช่นนี้

Address     Data           Meaning
0x12345678  00 00 00 05    // The variable i
0x1234567C  00 00 00 06    // The variable j

ตอนนี้เราต้องการที่จะชี้ไปที่ตัวแปรเหล่านี้ เราสร้างตัวชี้ไปยัง int, และหนึ่งint* ip1 int* ip2เช่นเดียวกับทุกสิ่งในคอมพิวเตอร์ตัวแปรตัวชี้เหล่านี้จะถูกจัดสรรไว้ในหน่วยความจำเช่นกัน jให้ถือว่าพวกเขาจบลงที่อยู่ติดกันต่อไปในหน่วยความจำได้ทันทีหลังจากที่ เราตั้งตัวชี้ที่จะมีที่อยู่ของตัวแปรที่จัดสรรไว้ก่อนหน้านี้: ip1=&i;( "คัดลอกที่อยู่ของฉันเข้าไปใน IP1") ip2=&jและ เกิดอะไรขึ้นระหว่างบรรทัดคือ:

Address     Data           Meaning
0x12345680  12 34 56 78    // The variable ip1(equal to address of i)
0x12345684  12 34 56 7C    // The variable ip2(equal to address of j)

ดังนั้นสิ่งที่เราได้รับก็คือบางส่วนของหน่วยความจำ 4 ไบต์ที่มีตัวเลข ไม่มีลูกศรลึกลับหรือเวทย์มนตร์ใด ๆ ในสายตา

ในความเป็นจริงเพียงแค่มองการถ่ายโอนข้อมูลหน่วยความจำเราไม่สามารถบอกได้ว่าที่อยู่ 0x12345680 มีหรือint int*ความแตกต่างคือวิธีที่โปรแกรมของเราเลือกใช้เนื้อหาที่เก็บไว้ตามที่อยู่นี้ (หน้าที่ของโปรแกรมของเราคือการบอกซีพียูว่าจะทำอย่างไรกับตัวเลขเหล่านี้)

int** ipp = &ip1;แล้วเรายังเพิ่มระดับของความร้ายอีกด้วย อีกครั้งเราเพิ่งได้รับความทรงจำอันมากมาย:

Address     Data           Meaning
0x12345688  12 34 56 80    // The variable ipp

รูปแบบดูเหมือนคุ้นเคย อีกอันของ 4 ไบต์ที่บรรจุตัวเลข

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

ดังนั้นถ้าเรานำเนื้อหาของ ipp *ippเราจะได้ที่อยู่ของตัวแปรพip1อยน์เตอร์ โดยการเขียน*ipp=ip2เราคัดลอก IP2 เข้า IP1 ip1=ip2ก็จะเทียบเท่ากับ ไม่ว่าในกรณีใดเราจะได้รับ

Address     Data           Meaning
0x12345680  12 34 56 7C    // The variable ip1
0x12345684  12 34 56 7C    // The variable ip2

(ตัวอย่างเหล่านี้มอบให้กับ CPU endian ขนาดใหญ่)


5
แม้ว่าฉันจะชี้ประเด็นของคุณ แต่ก็มีค่าในการคิดพอยน์เตอร์ที่เป็นนามธรรมและลึกลับ การใช้งานพอยน์เตอร์แบบพิเศษใด ๆเป็นเพียงตัวเลข แต่กลยุทธ์การดำเนินการที่คุณร่างไม่ได้เป็นข้อกำหนดของการใช้งานมันเป็นเพียงกลยุทธ์ทั่วไป พอยน์เตอร์ไม่จำเป็นต้องมีขนาดเท่ากันกับ int พอยน์เตอร์ไม่จำเป็นต้องมีที่อยู่ในรูปแบบหน่วยความจำเสมือนแบบแบนและอื่น ๆ ; เหล่านี้เป็นเพียงรายละเอียดการใช้งาน
Eric Lippert

@EricLippert ฉันคิดว่าสามารถทำให้ตัวอย่างนี้เป็นนามธรรมมากขึ้นโดยไม่ใช้ที่อยู่หน่วยความจำจริงหรือบล็อกข้อมูล หากเป็นตารางที่ระบุว่าlocation, value, variableสถานที่ตั้ง1,2,3,4,5และค่าเป็นA,1,B,C,3เช่นใดความคิดที่สอดคล้องกันของตัวชี้สามารถอธิบายได้อย่างง่ายดายโดยไม่ต้องใช้ลูกศรซึ่งทำให้เกิดความสับสนโดยเนื้อแท้ เมื่อมีการติดตั้งใช้งานอะไรก็ตามจะมีค่าอยู่ในบางตำแหน่งและนี่คือส่วนหนึ่งของปริศนาที่สับสนเมื่อทำการสร้างโมเดลด้วยลูกศร
MirroredFate

@EricLippert จากประสบการณ์ของฉันโปรแกรมเมอร์ C ส่วนใหญ่ที่มีปัญหาในการทำความเข้าใจพอยน์เตอร์เป็นผู้ที่ได้รับนามธรรมแบบจำลองเทียม สิ่งที่เป็นนามธรรมไม่เป็นประโยชน์เพราะจุดประสงค์ทั้งหมดของภาษา C ในปัจจุบันคือมันอยู่ใกล้กับฮาร์ดแวร์ หากคุณกำลังเรียนรู้ C แต่ไม่ได้ตั้งใจที่จะเขียนโค้ดใกล้กับฮาร์ดแวร์คุณจะเสียเวลาของคุณ Java etc เป็นตัวเลือกที่ดีกว่าถ้าคุณไม่ต้องการรู้ว่าคอมพิวเตอร์ทำงานอย่างไร แต่เพียงเขียนโปรแกรมระดับสูง
Lundin

@EricLippert และใช่อาจมีการใช้งานพอยน์เตอร์ที่ไม่ชัดเจนของพอยน์เตอร์ซึ่งพอยน์เตอร์ไม่จำเป็นต้องสอดคล้องกับที่อยู่ แต่การวาดลูกศรจะไม่ช่วยให้คุณเข้าใจว่ามันทำงานอย่างไร ในบางจุดคุณต้องทิ้งความคิดที่เป็นนามธรรมและลงไปถึงระดับฮาร์ดแวร์มิฉะนั้นคุณไม่ควรใช้ C. มีภาษาที่ทันสมัยและเหมาะสมสำหรับการเขียนโปรแกรมระดับสูงที่เป็นนามธรรมล้วนๆ
Lundin

@Lundin: ฉันไม่ใช่แฟนตัวยงของลูกศรไดอะแกรมเช่นกัน แนวคิดของลูกศรในขณะที่ข้อมูลเป็นสิ่งที่ยุ่งยาก ฉันชอบคิดว่ามันเป็นนามธรรม แต่ไม่มีลูกธนู &ผู้ประกอบการเกี่ยวกับตัวแปรที่จะช่วยให้คุณเหรียญที่แสดงถึงตัวแปรที่ *ผู้ประกอบการเกี่ยวกับเหรียญที่ช่วยให้คุณสำรองตัวแปร ไม่ต้องใช้ลูกศร!
Eric Lippert

8

สังเกตเห็นการมอบหมาย:

ipp = &ip1;

ผลที่จะชี้ไปที่ippip1

ดังนั้นippเพื่อชี้ไปที่ip2เราควรเปลี่ยนในลักษณะที่คล้ายกัน

ipp = &ip2;

ซึ่งเราไม่ได้ทำอย่างชัดเจน แต่เรากำลังเปลี่ยนค่าตามที่อยู่ที่ชี้ippไป
ด้วยวิธีการทำ folowing

*ipp = ip2;

ip1เราเป็นเพียงการเปลี่ยนค่าที่เก็บไว้ใน

ipp = &ip1หมายถึง*ipp = ip1 = &i, ตอนนี้
ดังนั้นเป็นหลักเช่นเดียวกับ*ipp = ip2 = &j
*ipp = ip2ip1 = ip2


5
ipp = &ip1;

ippไม่มีการกำหนดในภายหลังมีการเปลี่ยนแปลงค่าของ ip1นี่คือเหตุผลที่มันยังคงชี้ไปที่

สิ่งที่คุณทำด้วย*ippคือมีip1ไม่เปลี่ยนความจริงที่ว่าจุดที่จะต้องippip1


5

คำถามของฉันคือ: ทำไมในภาพที่สอง, ipp ยังคงชี้ไปที่ ip1 แต่ไม่ใช่ ip2?

คุณวางภาพที่ดีฉันจะพยายามทำให้ศิลปะ ASCII ที่ดี:

เช่น @ Robert-S-Barnes กล่าวในคำตอบของเขา: ลืมเกี่ยวกับพอยน์เตอร์และสิ่งที่ชี้ไปที่อะไร แต่คิดในแง่ของหน่วยความจำ โดยทั่วไปint*หมายถึงว่ามันมีที่อยู่ของตัวแปรและint**มีที่อยู่ของตัวแปรที่มีที่อยู่ของตัวแปร แล้วคุณสามารถใช้พีชคณิตชี้ของการเข้าถึงค่าหรือที่อยู่: &fooวิธีการaddress of fooและวิธีการ*foovalue of the address contained in foo

ดังนั้นเมื่อพอยน์เตอร์เกี่ยวกับการจัดการกับหน่วยความจำวิธีที่ดีที่สุดในการทำให้ "จับต้องได้" คือการแสดงให้เห็นว่าพีชคณิตพอยน์เตอร์ทำอะไรกับหน่วยความจำ

ดังนั้นนี่คือหน่วยความจำของโปรแกรมของคุณ (ง่ายสำหรับวัตถุประสงค์ของตัวอย่าง):

name:    i   j ip1 ip2 ipp
addr:    0   1   2   3   4
mem : [   |   |   |   |   ]

เมื่อคุณทำรหัสเริ่มต้นของคุณ:

int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;

นี่คือลักษณะความจำของคุณ:

name:    i   j ip1 ip2
addr:    0   1   2   3
mem : [  5|  6|  0|  1]

ที่นั่นคุณสามารถดูip1และip2รับที่อยู่ของiและjและippยังไม่มีอยู่ อย่าลืมว่าที่อยู่นั้นเป็นจำนวนเต็มเพียงเก็บไว้ในประเภทพิเศษ

จากนั้นคุณประกาศและกำหนดippเช่น:

int **ipp = &ip1;

ดังนั้นนี่คือความทรงจำของคุณ:

name:    i   j ip1 ip2 ipp
addr:    0   1   2   3   4
mem : [  5|  6|  0|  1|  2]

จากนั้นคุณเปลี่ยนค่าที่ชี้ไปยังที่อยู่ที่เก็บไว้ippซึ่งเป็นที่อยู่ที่เก็บไว้ในip1:

*ipp = ip2;

หน่วยความจำของโปรแกรมคือ

name:    i   j ip1 ip2 ipp
addr:    0   1   2   3   4
mem : [  5|  6|  1|  1|  2]

หมายเหตุ: เนื่องจากint*เป็นประเภทพิเศษฉันชอบหลีกเลี่ยงการประกาศพอยน์เตอร์หลายรายการในบรรทัดเดียวกันเสมอเพราะฉันคิดว่าสัญลักษณ์int *x;หรือint *x, *y;อาจทำให้เข้าใจผิด ฉันชอบที่จะเขียนint* x; int* y;

HTH


มีตัวอย่างของค่าเริ่มต้นของip2ที่ควรจะเป็นไม่ได้3 4
Dipto

1
โอ้ฉันเพิ่งเปลี่ยนหน่วยความจำเพื่อให้ตรงกับคำสั่งของการประกาศ ฉันเดาว่าคงทำเช่นนั้น?
zmo

5

เพราะเมื่อคุณพูด

*ipp = ip2

คุณกำลังบอกว่า 'วัตถุที่ถูกชี้ipp' เพื่อชี้ทิศทางของหน่วยความจำที่ip2กำลังชี้

คุณไม่ได้พูดถึงจุดippip2


4

ถ้าคุณเพิ่มตัวดำเนินการ dereference *ไปยังตัวชี้คุณเปลี่ยนเส้นทางจากตัวชี้ไปยังวัตถุที่ชี้ไปที่

ตัวอย่าง:

int i = 0;
int *p = &i; // <-- N.B. the pointer declaration also uses the `*`
             //     it's not the dereference operator in this context
*p;          // <-- this expression uses the pointed-to object, that is `i`
p;           // <-- this expression uses the pointer object itself, that is `p`

ดังนั้น:

*ipp = ip2; // <-- you change the pointer `ipp` points to, not `ipp` itself
            //     therefore, `ipp` still points to `ip1` afterwards.

3

หากคุณต้องการippให้ชี้ไปที่คุณต้องการได้กล่าวip2 ipp = &ip2;แต่นี้จะออกยังคงชี้ไปที่ip1i



3

พิจารณาตัวแปรแต่ละตัวที่แสดงดังนี้:

type  : (name, adress, value)

ดังนั้นตัวแปรของคุณควรเป็นแบบนี้

int   : ( i ,  &i , 5 ); ( j ,  &j ,  6); ( k ,  &k , 5 )

int*  : (ip1, &ip1, &i); (ip1, &ip1, &j)

int** : (ipp, &ipp, &ip1)

ในฐานะที่เป็นค่าของการippมี&ip1เพื่อ inctruction นี้:

*ipp = ip2;

เปลี่ยนค่าที่ addess &ip1เป็นค่าของip2ซึ่งหมายความว่าip1มีการเปลี่ยนแปลง:

(ip1, &ip1, &i) -> (ip1, &ip1, &j)

แต่ippก็ยัง:

(ipp, &ipp, &ip1)

ดังนั้นค่าของippยังคงซึ่งหมายความว่ามันยังคงชี้ไปที่&ip1ip1


1

*ippเพราะคุณจะมีการเปลี่ยนแปลงตัวชี้ของ มันหมายถึง

  1. ipp (ชื่อ varaiable) ---- เข้าไปข้างใน
  2. ข้างในippเป็นที่อยู่ของip1.
  3. ตอนนี้*ippจึงไป ip1(ที่อยู่ภายใน)

ip1ตอนนี้เราอยู่ที่ *ipp(เช่นip1) = ip2.
ip2มีที่อยู่ของ. jso ip1เนื้อหาจะถูกแทนที่โดยประกอบด้วยของ ip2 (เช่นที่อยู่ของ j) เราไม่ได้เปลี่ยนippเนื้อหา แค่นั้นแหละ.


1

*ipp = ip2; หมายถึง:

กำหนดให้กับตัวแปรที่ชี้ไปตามip2 ippดังนั้นนี่เท่ากับ:

ip1 = ip2;

หากคุณต้องการเก็บที่อยู่ของip2ให้ippทำ:

ipp = &ip2;

ตอนนี้ชี้ไปที่ippip2


0

ippสามารถเก็บค่าของ (เช่นชี้ไปที่) ตัวชี้ไปยังวัตถุประเภทตัวชี้ เมื่อคุณทำ

ipp = &ip2;  

แล้วippมีอยู่ของตัวแปร (ตัวชี้)ip2ซึ่งเป็น ( &ip2) ประเภทตัวชี้ไปชี้ ตอนนี้ลูกศรของในรูปที่สองจะชี้ไปที่ ippip2

วิกิพีเดียบอกว่า: ผู้ประกอบการเป็นผู้ประกอบการ dereference ทำงานบนตัวแปรชี้และส่งกลับลิตรมูลค่า (ตัวแปร) เทียบเท่ากับค่าที่อยู่ที่ตัวชี้ สิ่งนี้เรียกว่าการยกเลิกการลงทะเบียนตัวชี้
*

การใช้*โอเปอเรเตอร์ในการippยกเลิกการลงทะเบียนกับค่า l ของตัวชี้เพื่อintพิมพ์ l- ค่า dereferenced *ippเป็นประเภทของตัวชี้ไปที่intมันสามารถเก็บที่อยู่ของintข้อมูลประเภท หลังจากการแถลง

ipp = &ip1;

ippมีการถือครองที่อยู่ของip1และ*ippมีการถือครองอยู่ของ i(ชี้เฉพาะ) คุณสามารถพูดได้ว่าเป็นนามแฝงของ*ipp ip1ทั้งสอง**ippและมีนามแฝงสำหรับ*ip1 จากการทำ i

 *ipp = ip2;  

*ippและip2จุดทั้งสองไปยังตำแหน่งเดิม แต่ยังคงชี้ไปที่ ippip1

สิ่งที่*ipp = ip2;จริงคือการที่มันคัดลอกเนื้อหาของip2(ที่อยู่ของj) ไปยังip1(ตามที่*ippเป็นนามแฝงip1) มีผลทำให้ตัวชี้ip1และip2ชี้ไปที่วัตถุเดียวกัน ( j)
ดังนั้นในรูปที่สองลูกศรของip1และip2จะชี้ไปjในขณะที่ippยังคงชี้ไปที่ip1ippเป็นการปรับเปลี่ยนไม่ได้ทำเพื่อเปลี่ยนค่าของ

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