เป็นไปได้หรือไม่ที่จะเริ่มต้นตัวชี้ C เป็น NULL


90

ฉันเคยเขียนสิ่งต่างๆเช่น

บนสมมติฐานที่ว่า

จะสร้างcharตัวชี้ไปยังที่อยู่ 2

แต่ในบทช่วยสอนการเขียนโปรแกรม GNU Cบอกว่าจะint *my_int_ptr = 2;เก็บค่าจำนวนเต็ม2ไว้ที่ที่อยู่แบบสุ่มใด ๆ ก็ตามmy_int_ptrเมื่อมีการจัดสรร

สิ่งนี้ดูเหมือนจะบอกเป็นนัยว่าของฉันเองchar *x=NULLกำลังกำหนดค่าของการNULLร่ายให้กับ a charคือที่อยู่แบบสุ่มบางส่วนในหน่วยความจำ

ในขณะที่

ในความเป็นจริงพิมพ์

เป็นโมฆะ

เมื่อฉันรวบรวมและเรียกใช้ฉันกังวลว่าฉันกำลังอาศัยพฤติกรรมที่ไม่ได้กำหนดหรืออย่างน้อยพฤติกรรมที่ไม่ระบุและฉันควรเขียน

แทน.


72
มีความแตกต่างที่สับสนระหว่างสิ่งที่int *x = whatever;ทำและสิ่งที่int *x; *x = whatever;ทำ int *x = whatever;จริงพฤติกรรมเช่นไม่int *x; x = whatever; *x = whatever;
user2357112 รองรับ Monica

78
บทช่วยสอนนี้ดูเหมือนจะมีความแตกต่างที่สับสนผิด
user2357112 รองรับ Monica

51
บทเรียนห่วย ๆ มากมายบนเว็บ! หยุดอ่านทันที เราต้องการบัญชีดำดังนั้นเราจึงสามารถเผยแพร่หนังสือเส็งเคร็งต่อสาธารณชนได้ ...
Lundin

9
@MM ซึ่งไม่ได้ทำให้เส็งเคร็งน้อยลงในปี 2017 ด้วยวิวัฒนาการของคอมไพเลอร์และคอมพิวเตอร์ตั้งแต่ยุค 80 โดยพื้นฐานแล้วมันก็เหมือนกับว่าฉันเป็นหมอและอ่านหนังสือยาที่เขียนขึ้นในช่วงศตวรรษที่ 18
Lundin

13
ฉันไม่คิดว่านี้มีคุณสมบัติการกวดวิชาเป็น " GNU C Programming สอน" ...
marcelm

คำตอบ:


114

เป็นไปได้หรือไม่ที่จะเริ่มต้นตัวชี้ C เป็น NULL

TL; DRใช่มาก


เรียกร้องที่เกิดขึ้นจริงในวันที่คู่มืออ่านเหมือน

ในทางกลับกันถ้าคุณใช้การกำหนดเริ่มต้นเพียงครั้งเดียวint *my_int_ptr = 2;โปรแกรมจะพยายามเติมเนื้อหาของตำแหน่งหน่วยความจำที่ชี้ไปmy_int_ptrด้วยค่า 2 เนื่องจากmy_int_ptrเต็มไปด้วยขยะจึงสามารถเป็นที่อยู่ใดก็ได้ [... ]

ดีที่พวกเขามีความผิดคุณมีสิทธิ

สำหรับคำสั่ง ( ไม่สนใจในตอนนี้ความจริงที่ว่าตัวชี้ไปยังการแปลงจำนวนเต็มเป็นพฤติกรรมที่กำหนดโดยการนำไปใช้งาน )

my_int_ptrเป็นตัวแปร (ชนิดของตัวชี้ไปที่int) มีที่อยู่ของตัวเอง (ประเภท: ที่อยู่ของตัวชี้เป็นจำนวนเต็ม) คุณกำลังจัดเก็บค่า2ไว้ในที่อยู่นั้น

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

ดังนั้นสำหรับข้อสรุป

เริ่มต้นตัวแปรชี้xจะNULLไม่คุ้มค่าที่อยู่หน่วยความจำที่ชี้ไปตามตัวชี้

นี่คือเดียวกันเป็น


การขยาย:

ตอนนี้กำลังปฏิบัติตามอย่างเคร่งครัดคำสั่งเช่น

ผิดกฎหมายเนื่องจากเกี่ยวข้องกับการละเมิดข้อ จำกัด ต้องมีความชัดเจน,

  • my_int_ptr เป็นตัวแปรตัวชี้ชนิด int *
  • ค่าคงที่จำนวนเต็ม2มีชนิดintตามนิยาม

และพวกเขาไม่ได้เป็นประเภท "เข้ากันได้" ดังนั้นการเริ่มต้นนี้ไม่ถูกต้องเพราะการละเมิดกฎของงานที่เรียบง่ายที่กล่าวถึงในบท§6.5.16.1 / P1 ที่อธิบายไว้ในคำตอบของ Lundin

ในกรณีที่ใครก็ตามที่สนใจว่าการเริ่มต้นเชื่อมโยงกับข้อ จำกัด ของการมอบหมายอย่างง่ายการอ้างอิงC11บทที่§6.7.9, P11

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


@ Random832n พวกเขามีความผิด ฉันได้อ้างถึงส่วนที่เกี่ยวข้องในคำตอบของฉันแล้วโปรดแก้ไขฉันหากเป็นอย่างอื่น โอ้และเน้นความตั้งใจ
Sourav Ghosh

"... ผิดกฎหมายเนื่องจากเกี่ยวข้องกับการละเมิดข้อ จำกัด ... ลิเทอรัลจำนวนเต็ม 2 มีประเภท int ตามความหมาย" เป็นปัญหา ดูเหมือนว่าเพราะ2เป็นintงานที่มอบหมายเป็นปัญหา แต่มันเป็นมากกว่านั้น NULLอาจintเป็นint 0ไฟล์. เป็นเพียงที่char *x = 0;กำหนดไว้อย่างดีและchar *x = 2;ไม่เป็นเช่นนั้น 6.3.2.3 ตัวชี้ 3 (BTW: C ไม่ได้กำหนดตัวอักษรจำนวนเต็มเพียงตัวอักษรสตริงและตัวอักษรสารประกอบ . 0เป็นเลขคงที่ )
Chux - คืนสิทธิ์ให้กับโมนิกา

@chux คุณถูกต้องมาก แต่ไม่char *x = (void *)0;เป็นไปตามนั้นหรือ? หรือเป็นเฉพาะกับนิพจน์อื่นที่ให้ค่า0?
Sourav Ghosh

10
@SouravGhosh: ค่าคงที่เป็นจำนวนเต็มมีค่า0พิเศษ: โดยปริยายจะแปลงเป็นพอยน์เตอร์ว่างแยกจากกฎปกติสำหรับการแคสต์นิพจน์จำนวนเต็มทั่วไปอย่างชัดเจนเป็นชนิดตัวชี้
Steve Jessop

1
ภาษาที่อธิบายโดยคู่มืออ้างอิง C ปี 1974ไม่อนุญาตให้มีการประกาศเพื่อระบุนิพจน์การเริ่มต้นและการขาดนิพจน์ดังกล่าวทำให้ "กระจกประกาศใช้" ในทางปฏิบัติมากขึ้น ไวยากรณ์int *p = somePtrExpressionเป็น IMHO ค่อนข้างน่ากลัวเนื่องจากดูเหมือนว่าจะตั้งค่า*pแต่จริงๆแล้วเป็นการตั้งค่าของp.
supercat

53

กวดวิชาไม่ถูกต้อง ใน ISO C int *my_int_ptr = 2;เป็นข้อผิดพลาด ใน GNU C หมายถึงเช่นเดียวกับint *my_int_ptr = (int *)2;. สิ่งนี้จะแปลงจำนวนเต็ม2เป็นที่อยู่หน่วยความจำในบางรูปแบบตามที่คอมไพเลอร์กำหนด

ไม่พยายามจัดเก็บสิ่งใด ๆ ในสถานที่ที่ระบุโดยที่อยู่นั้น (ถ้ามี) หากคุณเขียน*my_int_ptr = 5;ต่อไประบบจะพยายามจัดเก็บหมายเลข5ในตำแหน่งที่ระบุโดยที่อยู่นั้น


1
ฉันไม่ทราบว่าการแปลงจำนวนเต็มเป็นตัวชี้มีการกำหนดการใช้งาน ขอบคุณสำหรับข้อมูล.
taskinoor

1
@taskinoor โปรดทราบว่ามีการแปลงเฉพาะในกรณีที่คุณบังคับโดยนักแสดงดังในคำตอบนี้ หากไม่ใช่สำหรับนักแสดงโค้ดไม่ควรคอมไพล์
Lundin

2
@taskinoor: ใช่การแปลงต่างๆใน C ค่อนข้างสับสน คำถามนี้มีข้อมูลที่น่าสนใจเกี่ยวกับการแปลง: C: เมื่อใดที่การแคสต์ระหว่างประเภทตัวชี้ไม่ใช่พฤติกรรมที่ไม่ได้กำหนด .
sleske

17

เพื่อชี้แจงว่าเหตุใดบทช่วยสอนจึงไม่ถูกต้องint *my_int_ptr = 2;เป็น "การละเมิดข้อ จำกัด " เป็นรหัสที่ไม่ได้รับอนุญาตให้รวบรวมและคอมไพเลอร์จะต้องให้การวินิจฉัยแก่คุณเมื่อพบ

ตาม 6.5.16.1 การมอบหมายอย่างง่าย:

ข้อ จำกัด

ข้อใดข้อหนึ่งต่อไปนี้จะถือ:

  • ตัวถูกดำเนินการด้านซ้ายมีประเภทเลขคณิตเชิงอะตอมคุณสมบัติหรือไม่มีเงื่อนไขและทางขวามีประเภทเลขคณิต
  • ตัวถูกดำเนินการด้านซ้ายมีโครงสร้างหรือชนิดยูเนี่ยนแบบอะตอมคุณสมบัติหรือไม่มีเงื่อนไขที่เข้ากันได้กับประเภทของด้านขวา
  • ตัวถูกดำเนินการด้านซ้ายมีประเภทตัวชี้แบบอะตอมคุณสมบัติหรือไม่มีเงื่อนไขและ (พิจารณาจากประเภทที่ตัวถูกดำเนินการด้านซ้ายจะมีหลังจากการแปลงค่า lvalue) ตัวถูกดำเนินการทั้งสองเป็นตัวชี้ไปยังรุ่นที่เข้ากันได้ที่มีคุณสมบัติหรือไม่มีเงื่อนไขและประเภทที่ชี้ไปทางซ้ายมีทั้งหมด คุณสมบัติของประเภทที่ชี้ไปทางขวา
  • ตัวถูกดำเนินการด้านซ้ายมีชนิดของตัวชี้แบบอะตอมคุณสมบัติหรือไม่มีเงื่อนไขและ (พิจารณาจากประเภทที่ตัวถูกดำเนินการด้านซ้ายจะมีหลังจากการแปลงค่า lvalue) ตัวถูกดำเนินการตัวหนึ่งเป็นตัวชี้ไปยังประเภทวัตถุและอีกตัวหนึ่งเป็นตัวชี้ไปยังเวอร์ชันที่มีคุณสมบัติหรือไม่มีเงื่อนไขของ เป็นโมฆะและประเภทที่ชี้ไปทางซ้ายมีคุณสมบัติทั้งหมดของประเภทที่ชี้ไปทางขวา
  • ตัวถูกดำเนินการด้านซ้ายเป็นตัวชี้อะตอมที่มีคุณสมบัติหรือไม่มีเงื่อนไขและทางขวาเป็นค่าคงที่ของตัวชี้ที่เป็นค่าว่าง หรือ
  • ตัวถูกดำเนินการด้านซ้ายมีประเภทอะตอมมีคุณสมบัติหรือไม่มีเงื่อนไข _Bool และทางขวาเป็นตัวชี้

ในกรณีนี้ตัวถูกดำเนินการด้านซ้ายเป็นตัวชี้ที่ไม่มีเงื่อนไข ไม่มีที่ไหนกล่าวถึงตัวถูกดำเนินการที่ถูกต้องได้รับอนุญาตให้เป็นจำนวนเต็ม (ประเภทเลขคณิต) ดังนั้นรหัสจึงละเมิดมาตรฐาน C

เป็นที่ทราบกันดีว่า GCC ทำงานได้ไม่ดีเว้นแต่คุณจะบอกอย่างชัดเจนว่าเป็นคอมไพเลอร์ C มาตรฐาน หากคุณคอมไพล์โค้ดเป็น-std=c11 -pedantic-errorsก็จะทำการวินิจฉัยได้อย่างถูกต้องตามที่ต้องทำ


4
เพิ่มคะแนนสำหรับข้อเสนอแนะ -pedantic-error แม้ว่าฉันจะใช้ -Wpedantic ที่เกี่ยวข้อง
fagricipni

2
ข้อยกเว้นประการหนึ่งสำหรับคำสั่งของคุณที่ว่าตัวถูกดำเนินการด้านขวาไม่ได้รับอนุญาตให้เป็นจำนวนเต็ม: ส่วน 6.3.2.3 กล่าวว่า“ นิพจน์คงที่จำนวนเต็มที่มีค่า 0 หรือนิพจน์ที่ส่งไปพิมพ์void *เรียกว่าค่าคงที่ของพอยน์เตอร์ว่าง” สังเกตสัญลักษณ์แสดงหัวข้อย่อยที่สองถึงสุดท้ายในคำพูดของคุณ ดังนั้นเป็นวิธีที่ถูกต้องตามกฎหมายที่จะเขียนint* p = 0; int* p = NULL;แม้ว่าอย่างหลังจะชัดเจนและเป็นแบบแผนมากขึ้น
Davislor

1
ซึ่งทำให้ความสับสนทางพยาธิวิทยาint m = 1, n = 2 * 2, * p = 1 - 1, q = 2 - 1;ถูกกฎหมายด้วย
Davislor

@Davislor ซึ่งครอบคลุมด้วยสัญลักษณ์แสดงหัวข้อย่อย 5 ในคำพูดมาตรฐานในคำตอบนี้ (ยอมรับว่าบทสรุปหลังจากนั้นน่าจะกล่าวถึง)
MM

1
@chux ฉันเชื่อว่าโปรแกรมที่มีรูปแบบดีจะต้องแปลงintptr_tอย่างชัดเจนเป็นประเภทที่อนุญาตทางด้านขวามือ นั่นคือvoid* a = (void*)(intptr_t)b;เป็นกฎหมายโดย 4 จุด แต่(intptr_t)bไม่ใช่ประเภทที่รองรับตัวชี้และไม่void*หรือคงชี้โมฆะและไม่เป็นประเภทเลขคณิตมิได้void* a _Boolมาตรฐานกล่าวว่าการแปลงนั้นถูกกฎหมาย แต่ไม่ใช่ว่าเป็นการแปลงโดยปริยาย
Davislor

15

int *my_int_ptr = 2

เก็บค่าจำนวนเต็ม 2 เป็นที่อยู่สุ่มใด ๆ ที่อยู่ใน my_int_ptr เมื่อมีการจัดสรร

นี่เป็นสิ่งที่ผิดอย่างสิ้นเชิง ถ้าเขียนได้จริงโปรดหาหนังสือหรือบทช่วยสอนที่ดีกว่า

int *my_int_ptr = 2กำหนดตัวชี้จำนวนเต็มซึ่งจุดไปยังที่อยู่ 2. 2คุณมักจะได้รับความผิดพลาดถ้าคุณพยายามที่จะเข้าถึงที่อยู่

*my_int_ptr = 2กล่าวคือไม่มี intในบรรทัดจะเก็บค่าสองตามที่อยู่แบบสุ่มที่my_int_ptrชี้ไป เมื่อพูดสิ่งนี้คุณสามารถกำหนดให้NULLกับตัวชี้เมื่อมีการกำหนด char *x=NULL;ถูกต้องสมบูรณ์ C.

แก้ไข: ในขณะที่เขียนสิ่งนี้ฉันไม่ทราบว่าการแปลงจำนวนเต็มเป็นตัวชี้เป็นการใช้งานที่กำหนดไว้ โปรดดูคำตอบที่ดีโดย @MM และ @SouravGhosh เพื่อดูรายละเอียด


1
ถือเป็นความผิดอย่างสิ้นเชิงเนื่องจากเป็นการละเมิดข้อ จำกัด ไม่ใช่ด้วยเหตุผลอื่นใด โดยเฉพาะอย่างยิ่งสิ่งนี้ไม่ถูกต้อง: "int * my_int_ptr = 2 กำหนดตัวชี้จำนวนเต็มซึ่งชี้ไปที่ที่อยู่ 2"
Lundin

@ ลุนดิน: วลีของคุณ"ไม่ใช่ด้วยเหตุผลอื่นใด"นั้นผิดและทำให้เข้าใจผิด หากคุณแก้ไขปัญหาความเข้ากันได้ของประเภทคุณยังคงอยู่กับข้อเท็จจริงที่ว่าผู้เขียนบทช่วยสอนนั้นบิดเบือนความจริงอย่างสิ้นเชิงว่าการเริ่มต้นและการกำหนดตัวชี้ทำงานอย่างไร
Lightness Races in Orbit

14

ความสับสนมากมายเกี่ยวกับพอยน์เตอร์ C มาจากตัวเลือกที่ไม่ดีมากซึ่ง แต่เดิมสร้างขึ้นเกี่ยวกับรูปแบบการเข้ารหัสซึ่งได้รับการยืนยันจากตัวเลือกเล็ก ๆ น้อย ๆ ที่ไม่ดีในไวยากรณ์ของภาษา

int *x = NULL;ถูกต้อง C แต่มันทำให้เข้าใจผิดมากฉันจะพูดว่าไร้สาระและมันขัดขวางความเข้าใจภาษาสำหรับมือใหม่หลายคน มันทำให้เราคิดว่าในภายหลังเราสามารถทำได้*x = NULL;ซึ่งแน่นอนว่าเป็นไปไม่ได้ คุณจะเห็นว่าประเภทของตัวแปรไม่ใช่intและชื่อของตัวแปรไม่ใช่*xและ*ในการประกาศไม่มีบทบาทหน้าที่ในการทำงานร่วมกับ=. เป็นการประกาศอย่างหมดจด ดังนั้นสิ่งที่สมเหตุสมผลกว่านี้คือ:

int* x = NULL;ซึ่งก็ถูกต้องเช่นกันแม้ว่าจะไม่เป็นไปตามรูปแบบการเข้ารหัส K&R ดั้งเดิม มันทำให้ชัดเจนอย่างสมบูรณ์ว่าเป็นประเภทint*และตัวแปรตัวชี้คือxดังนั้นจึงเห็นได้ชัดแม้กระทั่งสำหรับผู้ที่ไม่ได้ฝึกหัดว่าNULLมีการจัดเก็บค่าไว้xซึ่งเป็นตัวชี้ไปที่intซึ่งเป็นตัวชี้ไปยัง

นอกจากนี้ยังทำให้ง่ายต่อการได้รับกฎ: เมื่อดาวอยู่ห่างจากชื่อตัวแปรจะเป็นการประกาศในขณะที่ดาวที่ติดอยู่กับชื่อจะเป็นการยกเลิกการอ้างอิงตัวชี้

ดังนั้นตอนนี้จึงเข้าใจได้ง่ายขึ้นมากว่ายิ่งไปกว่านั้นเราสามารถทำได้x = NULL;หรือ*x = 2;กล่าวอีกนัยหนึ่งก็คือทำให้มือใหม่ดูวิธีvariable = expressionนำไปสู่pointer-type variable = pointer-expressionและdereferenced-pointer-variable = expressionได้ง่ายขึ้น (สำหรับการเริ่มต้นโดย 'นิพจน์' ฉันหมายถึง 'rvalue')

ตัวเลือกที่น่าเสียดายในไวยากรณ์ของภาษาคือเมื่อประกาศตัวแปรท้องถิ่นคุณสามารถพูดได้ว่าตัวint i, *p;ใดประกาศจำนวนเต็มและตัวชี้เป็นจำนวนเต็มดังนั้นจึงทำให้เชื่อว่า*เป็นส่วนที่มีประโยชน์ของชื่อ แต่มันไม่ใช่และไวยากรณ์นี้เป็นเพียงกรณีพิเศษที่เล่นโวหารเพิ่มเพื่อความสะดวกและในความคิดของฉันมันไม่ควรมีอยู่จริงเพราะมันทำให้กฎที่ฉันเสนอข้างต้นไม่ถูกต้อง เท่าที่ฉันรู้ไม่มีที่ไหนในภาษาที่ไวยากรณ์นี้มีความหมาย แต่แม้ว่าจะเป็นเช่นนั้นก็ยังชี้ให้เห็นถึงความคลาดเคลื่อนในการกำหนดประเภทตัวชี้ใน C ทุกที่อื่นในการประกาศตัวแปรเดียวในรายการพารามิเตอร์ ในสมาชิกโครงสร้าง ฯลฯ คุณสามารถประกาศพอยน์เตอร์type* pointer-variableแทนtype *pointer-variable; ถูกต้องตามกฎหมายและสมเหตุสมผลกว่า


int *x = NULL; is correct C, but it is very misleading, I would even say nonsensical,... ฉันต้องเห็นด้วยกับไม่เห็นด้วย It makes one think.... หยุดคิดอ่านหนังสือ C ก่อนไม่มีอาบัติ.
Sourav Ghosh

^^ สิ่งนี้จะสมเหตุสมผลสำหรับฉัน ดังนั้นฉันคิดว่ามันเป็นเรื่องส่วนตัว
Mike Nakis

5
@SouravGhosh ตามความเห็นฉันคิดว่า C ควรได้รับการออกแบบมาเพื่อให้int* somePtr, someotherPtrประกาศตัวชี้สองตัวอันที่จริงฉันเคยเขียนint* somePtrแต่นั่นนำไปสู่จุดบกพร่องที่คุณอธิบาย
fagricipni

1
@fagricipni ฉันหยุดใช้ไวยากรณ์การประกาศตัวแปรหลายตัวเพราะเหตุนี้ ฉันประกาศตัวแปรของฉันทีละตัว ถ้าฉันต้องการให้มันอยู่ในบรรทัดเดียวกันจริงๆฉันแยกพวกมันด้วยเซมิโคลอนแทนที่จะเป็นจุลภาค "ถ้าสถานที่ไม่ดีอย่าไปที่นั่น"
Mike Nakis

2
@fagricipni ถ้าฉันสามารถออกแบบ linux ตั้งแต่เริ่มต้นฉันจะใช้createแทนcreatไฟล์. :) ประเด็นคือมันเป็นยังไงและเราต้องปั้นตัวเองเพื่อปรับให้เข้ากับสิ่งนั้น ทุกอย่างเดือดขึ้นกับการเลือกส่วนตัวในตอนท้ายของวันเห็นด้วย
Sourav Ghosh

6

ฉันต้องการเพิ่มบางสิ่งที่ตั้งฉากกับคำตอบที่ยอดเยี่ยมมากมาย ที่จริงแล้วการเริ่มต้นไปNULLยังไม่ได้รับการปฏิบัติที่ไม่ดีและอาจมีประโยชน์หากตัวชี้นั้นอาจใช้หรือไม่ก็ได้เพื่อจัดเก็บบล็อกหน่วยความจำที่จัดสรรแบบไดนามิก

เนื่องจากเป็นไปตามมาตรฐาน ISO-IEC 9899 freeเป็น nop เมื่ออาร์กิวเมนต์เป็นNULLโค้ดด้านบน (หรือบางอย่างที่มีความหมายมากกว่าในบรรทัดเดียวกัน) จึงถูกต้อง


5
มันซ้ำซ้อนในการส่งผลลัพธ์ของ malloc ใน C เว้นแต่ว่าโค้ด C ควรคอมไพล์เป็น C ++ ด้วย
cat

คุณถูกต้องvoid*แปลงตามความจำเป็น แต่การมีโค้ดที่ทำงานร่วมกับ C และคอมไพเลอร์ C ++ อาจมีประโยชน์
Luca Citi

1
@LucaCiti C และ C ++ เป็นภาษาที่แตกต่างกัน มีเพียงข้อผิดพลาดที่รอคุณอยู่หากคุณพยายามรวบรวมไฟล์ต้นฉบับที่เขียนขึ้นโดยใช้คอมไพเลอร์ที่ออกแบบมาสำหรับอีกไฟล์หนึ่ง เหมือนกับการพยายามเขียนโค้ด C ที่คุณสามารถคอมไพล์โดยใช้เครื่องมือ Pascal
Evil Dog Pie

1
คำปรึกษาที่ดี. ฉัน (พยายาม) เริ่มต้นค่าคงที่ตัวชี้ของฉันเป็นบางสิ่งเสมอ ใน C สมัยใหม่ค่านี้มักจะเป็นค่าสุดท้ายและสามารถเป็นพconstอยน์เตอร์ที่ประกาศใน medias resแต่ถึงแม้ว่าพอยน์เตอร์จะต้องเปลี่ยนแปลงได้ (เช่นเดียวกับที่ใช้ในลูปหรือโดยrealloc()) การตั้งค่าให้NULLจับจุดบกพร่องที่มันถูกใช้มาก่อน มันถูกกำหนดด้วยมูลค่าที่แท้จริง ในระบบส่วนใหญ่NULLการยกเลิกการอ้างอิงจะทำให้เกิด segfault ณ จุดที่ล้มเหลว (แม้ว่าจะมีข้อยกเว้นก็ตาม) ในขณะที่ตัวชี้ที่ไม่ได้กำหนดค่าเริ่มต้นมีขยะและการเขียนลงในหน่วยความจำนั้นจะทำให้หน่วยความจำเสียหายโดยพลการ
Davislor

1
นอกจากนี้ยังง่ายมากที่จะเห็นในดีบักเกอร์ที่มีตัวชี้NULLแต่อาจเป็นเรื่องยากที่จะบอกตัวชี้ขยะจากตัวชี้ที่ถูกต้อง ดังนั้นจึงเป็นประโยชน์ในการตรวจสอบให้แน่ใจว่าพอยน์เตอร์ทั้งหมดถูกต้องเสมอหรือNULLจากช่วงเวลาของการประกาศ
Davislor


1

นี่คือความถูกต้อง

ฟังก์ชันนี้ถูกต้องสำหรับสิ่งที่ทำ กำหนดที่อยู่เป็น 0 ให้กับตัวชี้ถ่าน x นั่นคือมันชี้ตัวชี้ x ไปยังที่อยู่หน่วยความจำ 0

ทางเลือก:

ฉันเดาว่าสิ่งที่คุณต้องการคือ:


"กำหนดที่อยู่เป็น 0 ให้กับตัวชี้ถ่าน x" -> อาจจะ C ไม่ได้ระบุค่าของตัวชี้ แต่char* x = 0; if (x == 0)จะเป็นจริงเท่านั้น พอยน์เตอร์ไม่จำเป็นต้องเป็นจำนวนเต็ม
chux - คืนสถานะ Monica

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