เป็นที่เชื่อกันว่าโดยทั่วไปแล้วตำแหน่งล่วงหน้า ++ เพิ่มค่าของตัวแปรเป็น 1 จากนั้นใช้ค่าหลังจากเพิ่ม 1 เพื่อเข้าร่วมในการดำเนินการ ในขณะที่โพสต์ตำแหน่ง ++ ใช้ค่าเป็นครั้งแรกเพื่อเข้าร่วมในการดำเนินการแล้วเพิ่มค่าเป็น 1
มาดูตัวอย่างแรก:
การทดสอบแพ็คเกจ; คลาสสาธารณะ plus_test01 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {int i = 100; i = i ++; System.out.println (i); -เดาว่าผลลัพธ์คืออะไร?
มาดูอันที่สอง:
การทดสอบแพ็คเกจ; คลาสสาธารณะ plus_test02 {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {int k = 100; ในขณะที่ (จริง) {ถ้า (k ++> 100) {// system.out.println (k); หยุดพัก; } system.out.println (k); -เดาว่าผลลัพธ์คืออะไร?
ในความเป็นจริงไม่ว่าจะเป็นล่วงหน้า-++ หรือโพสต์-++ ค่าของตัวแปรจะเพิ่มขึ้นก่อน 1 ก่อนที่จะคำนวณต่อไป ความแตกต่างที่แท้จริงระหว่างทั้งสองคือ: pre-++ เพิ่มค่าของตัวแปรโดย 1 และใช้ค่าเพิ่มเพื่อทำการคำนวณในขณะที่โพสต์-++ กำหนดตัวแปรแรกให้กับตัวแปรชั่วคราวจากนั้นเพิ่ม 1 ลงในค่าของตัวแปรจากนั้นใช้ตัวแปรชั่วคราวเพื่อทำการคำนวณ
สำหรับตัวอย่างโค้ดต่อไปนี้ (คำนำหน้า ++):
int i = 1;
int j = ++ i*5;
ในความเป็นจริงประโยคที่สองเทียบเท่ากับ:
i+= 1; // เพิ่มฉันถึง 1
j = i*5; // คำนวณค่าหลังจากเพิ่ม 1 ด้วยผลลัพธ์คือ: 10
และสำหรับตัวอย่างโค้ดต่อไปนี้ (โพสต์-++):
int i = 1;
int j = i ++*5;
ประโยคที่สองเทียบเท่ากับ:
int temp = i; // กำหนด I ให้กับตัวแปรชั่วคราว
i+= 1; // เพิ่มฉันถึง 1
j = อุณหภูมิ*5; // คำนวณตัวแปรชั่วคราวกับมันผลลัพธ์คือ: 5
สำหรับตัวอย่างแรกมันเทียบเท่ากับ:
int temp = i;
i+= 1;
i = อุณหภูมิ; -
ดังนั้นผลลัพธ์ควรไม่เปลี่ยนแปลงนั่นคือ 100
รหัสแอสเซมบลีสำหรับตัวอย่างแรกคือ:
โมฆะคงที่สาธารณะหลัก (java.lang.string []); descriptor: ([ljava/lang/string;) V Flags: acc_public, acc_static รหัส: stack = 2, locals = 2, args_size = 1 0: bipush 100 2: istore_1 3: iload_1 4: iinc 1, 1 // java/lang/system.out: ljava/io/printstream; 11: iload_1 // พารามิเตอร์ที่โหลดเป็นที่สองในสแต็กนั่นคือมันยังคงเป็น 100 12: invokevirtual #22 // เมธอด java/io/printstream.println: (i) v 15: return
สำหรับตัวอย่างที่สองจริง ๆ แล้วมันไม่ยาก แต่ผลลัพธ์คือ 101 ให้ความสนใจกับกระบวนการและคุณไม่สามารถทำผิดพลาดได้ในอนาคต (กระบวนการคือ: ก่อนการเปรียบเทียบอุณหภูมิ = i, อุณหภูมิ> 100 เห็นได้ชัดว่าไม่ถือเป็นจริงข้าม i+= 1 กับประโยค Syso แน่นอนพิมพ์ 101 วนซ้ำอีกครั้งและยังมีอุณหภูมิ = i, อุณหภูมิ> 100 คราวนี้มันเป็นจริง
การรวบรวมตัวอย่างที่สอง (เลือกเฉพาะวิธีหลักเท่านั้น):
โมฆะคงที่สาธารณะหลัก (java.lang.string []); descriptor: ([ljava/lang/string;) V Flags: acc_public, acc_static รหัส: stack = 2, locals = 2, args_size = 1 0: bipush 100 // 100 push stack 2: istore_1 // save ไปยัง var ท้องถิ่นที่สอง ตำแหน่งที่ 2 ของ VAR ท้องถิ่น (ตัวแปรท้องถิ่นเพิ่มขึ้นผลลัพธ์ยังคงอยู่ใน var ท้องถิ่น 1 อันดับแรกของตัวถูกดำเนินการจะไม่เปลี่ยน) 7: bipush 100 // 100 push stack 9: IF_ICMPLE 15 // เปรียบเทียบค่าจำนวนเต็มสองตัวที่ด้านบนของ OperAnd Stack 1> ตัวถูกดำเนินการสแต็ค 2) 15: getstatic #2 // ฟิลด์ java/lang/system.out: ljava/io/printstream; 18: iload_1 // // โหลดจาก var ท้องถิ่นแรกแรก 19: invokevirtual #3 // เมธอด java/io/printstream.println: (i) v // โทรหาวิธีนี้ 22: goto 3 // กระโดดกลับไป 3 อีกครั้ง, วนซ้ำอีกครั้ง 25: return // ออก
ตัวอย่างที่สาม:
การทดสอบแพ็คเกจ; คลาสสาธารณะ plus_test03 {Static int proplus () {int i = 55; int j = ++ i; กลับ j; // 56} int postplus () {int i = 55; int j = i ++; กลับ j; // 55} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {system.out.println (proplus ()); // 56 System.out.println (postplus ()); // 55}}}การรวบรวมตัวอย่างที่สาม:
proplus int คงที่ (); descriptor: () ฉันตั้งค่าสถานะ: acc_static code: stack = 1, locals = 2, args_size = 0 0: bipush 55 // 55 สแต็ก 2: istore_0 // การจัดเก็บด้านบนของสแต็กอินสแต็กแรก // ด้านบนของสแต็กคือ var 9 ท้องถิ่นที่สอง: ireturnstatic int postplus (); descriptor: () ฉันตั้งค่าสถานะ: acc_static code: stack = 1, locals = 2, args_size = 0 0: bipush 55 2: istore_0 3: iload_0 // โหลดเพื่อสแต็ก 4: iinc 0, 1 // ตัวแรก
จะเห็นได้ว่าความแตกต่างระหว่างด้านหน้า ++ และด้านหลัง ++ เป็นส่วนสีน้ำเงินด้านบน (// ตัวแรก Var Plus 1) ซึ่งตรงกันข้าม สำหรับรุ่นก่อนหมายเลขใน var ท้องถิ่นจะถูกเพิ่ม 1 จากนั้นโหลดลงในสแต็กในขณะที่หลังจะถูกโหลดจากสแต็ก local var ไปยังสแต็กและจากนั้น var ท้องถิ่นจะถูกเพิ่ม 1 ซึ่งเทียบเท่ากับการสำรองข้อมูล
สรุปแล้ว:
หนึ่ง. ตำแหน่งล่วงหน้าและโพสต์ตำแหน่ง ++ ทั้งคู่เพิ่ม 1 ลงในค่าตัวแปรก่อนแทนที่จะเพิ่ม 1 ลงในตำแหน่งล่วงหน้า ++ จากนั้นคำนวณในขณะที่โพสต์ตำแหน่ง ++ ก่อนแล้วจึงคำนวณ
สอง. จากการพูดแบบโปรแกรมโพสต์-++ ครั้งแรกกำหนดตัวแปรให้กับตัวแปรชั่วคราวจากนั้นเพิ่มค่าของตัวแปรโดย 1 จากนั้นใช้ตัวแปรชั่วคราวเพื่อเข้าร่วมในการดำเนินการ
สาม. จากมุมมองของมุมมองค่าของตัวแปรจะถูกผลักไปยังสแต็กก่อนที่จะดำเนินการคำสั่งเพิ่มค่า (IINC) หลังจากดำเนินการคำสั่งเพิ่มมูลค่าแล้วค่าที่ผลักไปยังสแต็กจะถูกใช้
ฉันหวังว่าผ่านบทความนี้ฉันจะเข้าใจความแตกต่างระหว่างตำแหน่งล่วงหน้า ++ และการดำเนินงานโพสต์ตำแหน่ง ++ อย่างละเอียด ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!