พฤติกรรมที่ไม่ได้กำหนดจะเกิดขึ้นเมื่อโปรแกรมจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนดไม่ว่าจะเกิดอะไรขึ้นต่อไป อย่างไรก็ตามคุณให้ตัวอย่างต่อไปนี้
int num = ReadNumberFromConsole();
if (num == 3) {
PrintToConsole(num);
*((char*)NULL) = 0;
}
เว้นแต่คอมไพลเลอร์จะทราบคำจำกัดความของPrintToConsole
ก็ไม่สามารถลบif (num == 3)
เงื่อนไขได้ สมมติว่าคุณมีส่วนหัวของระบบที่มีการประกาศดังต่อไปนี้LongAndCamelCaseStdio.h
PrintToConsole
void PrintToConsole(int);
ไม่มีอะไรเป็นประโยชน์เลยใช่ไหม ตอนนี้เรามาดูกันว่าความชั่วร้าย (หรืออาจจะไม่ชั่วถึงขนาดพฤติกรรมที่ไม่ได้กำหนดอาจแย่ลง) ผู้ขายคืออะไรโดยการตรวจสอบคำจำกัดความที่แท้จริงของฟังก์ชันนี้
int printf(const char *, ...);
void exit(int);
void PrintToConsole(int num) {
printf("%d\n", num);
exit(0);
}
จริงๆแล้วคอมไพเลอร์ต้องสมมติว่าฟังก์ชันใด ๆ โดยพลการที่คอมไพเลอร์ไม่รู้ว่ามันทำอะไรอยู่อาจออกหรือทำให้เกิดข้อยกเว้น (ในกรณีของ C ++) คุณสามารถสังเกตได้ว่า*((char*)NULL) = 0;
จะไม่ถูกดำเนินการเนื่องจากการดำเนินการจะไม่ดำเนินต่อไปหลังจากนั้นPrintToConsole
โทร
พฤติกรรมที่ไม่ได้กำหนดจะเกิดขึ้นเมื่อใด PrintToConsole
ส่งคืนจริง คอมไพเลอร์คาดว่าสิ่งนี้จะไม่เกิดขึ้น (เนื่องจากจะทำให้โปรแกรมดำเนินการตามพฤติกรรมที่ไม่ได้กำหนดไม่ว่าจะเกิดอะไรขึ้นก็ตาม) ดังนั้นอะไรก็เกิดขึ้นได้
อย่างไรก็ตามลองพิจารณาอย่างอื่น สมมติว่าเรากำลังทำการตรวจสอบค่าว่างและใช้ตัวแปรหลังจากการตรวจสอบค่าว่าง
int putchar(int);
const char *warning;
void lol_null_check(const char *pointer) {
if (!pointer) {
warning = "pointer is null";
}
putchar(*pointer);
}
ในกรณีนี้สังเกตได้ง่ายว่าlol_null_check
ต้องใช้ตัวชี้ที่ไม่ใช่ NULL การกำหนดให้กับwarning
ตัวแปรGlobal non-volatile ไม่ใช่สิ่งที่สามารถออกจากโปรแกรมหรือทำให้เกิดข้อยกเว้นใด ๆ pointer
นี้ยังไม่ระเหยจึงไม่สามารถได้อย่างน่าอัศจรรย์เปลี่ยนค่าในช่วงกลางของฟังก์ชั่น (ถ้ามันไม่เป็นพฤติกรรมที่ไม่ได้กำหนด) การโทรlol_null_check(NULL)
จะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนดซึ่งอาจทำให้ไม่สามารถกำหนดตัวแปรได้ (เนื่องจาก ณ จุดนี้จะทราบข้อเท็จจริงที่ว่าโปรแกรมเรียกใช้พฤติกรรมที่ไม่ได้กำหนดไว้)
อย่างไรก็ตามพฤติกรรมที่ไม่ได้กำหนดหมายความว่าโปรแกรมสามารถทำอะไรก็ได้ ดังนั้นจึงไม่มีสิ่งใดหยุดพฤติกรรมที่ไม่ได้กำหนดไว้ไม่ให้ย้อนเวลากลับไปและทำให้โปรแกรมของคุณหยุดทำงานก่อนที่จะint main()
ดำเนินการบรรทัดแรก เป็นพฤติกรรมที่ไม่ได้กำหนดไม่จำเป็นต้องมีเหตุผล มันอาจผิดพลาดหลังจากพิมพ์ 3 แต่พฤติกรรมที่ไม่ได้กำหนดจะย้อนเวลากลับไปและหยุดทำงานก่อนที่คุณจะพิมพ์ 3 และใครจะรู้ว่าพฤติกรรมที่ไม่ได้กำหนดอาจเขียนทับ RAM ระบบของคุณและทำให้ระบบของคุณพังใน 2 สัปดาห์ต่อมา ในขณะที่โปรแกรมที่ไม่ได้กำหนดของคุณไม่ทำงาน