- เหตุใดจึงใช้พอยน์เตอร์แทนตัวแปรปกติ
คำตอบสั้น ๆ คือ: ไม่ ;-) พอยน์เตอร์จะถูกใช้เมื่อคุณไม่สามารถใช้สิ่งอื่นได้ อาจเป็นเพราะการขาดฟังก์ชั่นที่เหมาะสมประเภทข้อมูลที่ขาดหายไปหรือเพื่อความสมบูรณ์แบบ ด้านล่างเพิ่มเติม ...
- ฉันควรใช้พอยน์เตอร์เมื่อใดและที่ไหน
คำตอบสั้น ๆ ที่นี่คือ: ที่ที่คุณไม่สามารถใช้สิ่งอื่นได้ ใน C คุณไม่มีการสนับสนุนประเภทข้อมูลที่ซับซ้อนเช่นสตริง นอกจากนี้ยังไม่มีวิธีการส่งผ่านตัวแปร "โดยการอ้างอิง" ไปยังฟังก์ชัน นั่นคือสิ่งที่คุณต้องใช้พอยน์เตอร์ นอกจากนี้คุณสามารถให้พวกเขาชี้ไปที่แทบทุกอย่างรายการที่เชื่อมโยงสมาชิกของ structs และอื่น ๆ แต่อย่าไปลงที่นี่
- คุณใช้พอยน์เตอร์กับอาร์เรย์ได้อย่างไร
ด้วยความพยายามน้อยและสับสนมาก ;-) ถ้าเราพูดถึงชนิดข้อมูลอย่างง่ายเช่น int และ char จะมีความแตกต่างกันเล็กน้อยระหว่างอาร์เรย์และตัวชี้ การประกาศเหล่านี้คล้ายกันมาก (แต่ไม่เหมือนกัน - เช่นsizeof
จะคืนค่าต่างกัน):
char* a = "Hello";
char a[] = "Hello";
คุณสามารถเข้าถึงองค์ประกอบใด ๆ ในอาร์เรย์เช่นนี้
printf("Second char is: %c", a[1]);
ดัชนี 1 ตั้งแต่อาร์เรย์เริ่มต้นด้วยองค์ประกอบ 0 :-)
หรือคุณทำได้เช่นกัน
printf("Second char is: %c", *(a+1));
ต้องการตัวดำเนินการตัวชี้ (*) เนื่องจากเรากำลังบอก printf ว่าเราต้องการพิมพ์อักขระ หากไม่มี * การแสดงอักขระของที่อยู่หน่วยความจำเองจะถูกพิมพ์ ตอนนี้เรากำลังใช้ตัวละครแทน หากเราใช้% s แทน% c เราจะขอให้ printf พิมพ์เนื้อหาของที่อยู่หน่วยความจำที่ชี้โดย 'a' บวกหนึ่ง (ในตัวอย่างข้างต้น) และเราไม่ต้องใส่ * ข้างหน้า:
printf("Second char is: %s", (a+1)); /* WRONG */
แต่สิ่งนี้จะไม่เพียงพิมพ์อักขระที่สอง แต่แทนอักขระทั้งหมดในที่อยู่หน่วยความจำถัดไปจนกว่าจะพบอักขระ null (\ 0) และนี่คือสิ่งที่เริ่มเป็นอันตราย จะเกิดอะไรขึ้นถ้าคุณลองพิมพ์ตัวแปรของจำนวนเต็มชนิดโดยไม่ได้ตั้งใจแทนที่จะใช้ตัวชี้ถ่านด้วยตัวจัดรูปแบบ% s
char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);
สิ่งนี้จะพิมพ์สิ่งใดก็ตามที่พบในที่อยู่หน่วยความจำ 120 และทำการพิมพ์จนกว่าจะพบอักขระว่าง มันผิดและผิดกฎหมายในการดำเนินการคำสั่ง printf นี้ แต่มันอาจจะทำงานได้เนื่องจากตัวชี้เป็นประเภท int ในหลายสภาพแวดล้อม ลองนึกภาพปัญหาที่คุณอาจเกิดขึ้นหากคุณใช้ sprintf () แทนและกำหนดวิธีนี้ "char array" นานเกินไปให้กับตัวแปรอื่นซึ่งมีการจัดสรรพื้นที่ จำกัด เท่านั้น คุณน่าจะจบลงด้วยการเขียนทับสิ่งอื่นในหน่วยความจำและทำให้โปรแกรมของคุณพัง (ถ้าคุณโชคดี)
โอ้และถ้าคุณไม่ได้กำหนดค่าสตริงให้กับอาร์เรย์ / ตัวชี้เมื่อคุณประกาศคุณต้องจัดสรรจำนวนหน่วยความจำให้เพียงพอก่อนที่จะกำหนดค่า ใช้ malloc, calloc หรือคล้ายกัน สิ่งนี้เนื่องจากคุณได้ประกาศเพียงหนึ่งองค์ประกอบในอาเรย์ / ที่อยู่หน่วยความจำเดียวของคุณให้ชี้ไปที่ ดังนั้นนี่คือตัวอย่างเล็ก ๆ น้อย ๆ :
char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);
โปรดทราบว่าคุณยังคงสามารถใช้ตัวแปร x ได้หลังจากที่คุณได้ทำการจัดสรรหน่วยความจำที่ว่าง () ของหน่วยความจำแล้ว แต่คุณไม่ทราบว่ามีอะไรอยู่ในนั้น นอกจากนี้โปรดสังเกตว่าสอง printf () อาจให้ที่อยู่ที่แตกต่างกันเนื่องจากไม่มีการรับประกันว่าการจัดสรรหน่วยความจำครั้งที่สองจะดำเนินการในพื้นที่เดียวกับที่อยู่แรก