Trong Java
Để làm rõ mình so sánh hai trường hợp, sự khác biệt ở đây là thời điểm giá trị được đẩy vào Stack (Push)
Case 1:
int k = 5; /* 5 được đẩy (push) vào stack và sau đó return về cho k,
hay được lấy ra (Pop) gán cho k */
k = k++; /* Giá trị x hiện tại (5) được push vào stack và sau đó k được
tăng lên 1 là 6, nhưng trong stack vẫn còn giá trị cũ của k
là 5, giá trị này được pop ra và gán cho k, vậy k = 5 */
Case 2:
int k = 5;/* tương tự 5 được đẩy (push) vào stack và sau đó return về cho k,
hay được lấy ra (Pop) gán cho k */
k = ++k; /* k được tăng lên một đơn vị là thành 6, sau đó được
push vào stack, giá trị này sẽ được lấy ra để gán cho k nên k = 6 */
Nếu dấu Increment nằm sau (postfix) thì giá trị của biểu thức bên phải dấu bằng sẽ được đẩy vào stack rồi mới tăng, nên sự tăng ở đây vô nghĩa. Còn nếu ++ nằm trước (prefix) thì nó sẽ tăng rồi mới đẩy vào stack.
Stack ở đây là Operand stack, Operand stack nằm trong Frame, Frame thì nằm trong Stack.
Nếu bạn không hiểu stack là gì thì có thể hiểu quá trình trên như này:
Cái này được nói rất nhiều lần rồi, search trong forum cũng sẽ không ít topic nói về cái này.
Nó liên quan tới sequence point.
Một rule nhỏ cho C/C++ là ở mỗi sequence point, chỉ được cập nhật 1 biến 1 và 1 lần duy nhất, nếu không thì hành vi của nó sẽ không được xác định (Undefined Behavior)
k = k++ đã vô tình update biến k 2 lần (k++ và phép gán) ở trong cùng 1 sequence point. Và như ở trên, dẫn tới Undefined Behavior
The Standard states that
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.
IDE cũng chỉ là 1 công cụ do con người tạo ra, nhiều khi quy ước khác nhau nên khi chạy trên mỗi IDE lại cho 1 kết quả khác nhau. Quan trọng là phải hiểu được lí thuyết của ngôn ngữ và cách hoạt động của IDE, chứ không phải cứ dịch chương trình xong thấy kết quả thì cho rằng luôn luôn đúng.
Mình hiểu điều đó. Nên mình muốn nhắc nhở những người giải thích như đinh đóng cột là k == 5 hoặc k == 6 rồi đưa dẫn chứng dài dằng dặc nửa trang giấy nên suy nghĩ kỹ hơn :))
theo suy đoán là bằng 6.
toán chạy từ bên phải qua trái. nghĩa là k tăng lên 1 rồi gán lại cho k.
Theo mình biết thì gán trước tăng sau chứ :p. Cái này thuộc về độ ưu tiên của toán tử, bạn thử tìm hiểu về phần đó xem.
đầu tiên k = 5, sau đó gán biến k++ (k tăng thêm 1 đơn vị) => lúc này k = 6
int k =5; => k = 5
k=k++; => lúc đầu k được gán bằng k tức là k = 5, sau đó k được tăng lến tức k = 6
Kết quả cuối cùng là k = 6 nhưng do toán tử ++
k=6
lúc đầu k=5 sau đó biến k +1 lên rồi gán lại cho biến k
tức là k=5 sau đó +1=6 rồi gán lại cho k (cộng trước gán sau)
Đoạn code mà bạn đưa có thứ tự như sau:
int k = 5;
k = k;
k++;
Vậy k = 6
Ô, hoá ra phép gán
=
còn được ưu tiên hơn cả phép++
à O_oCứ tưởng
k++
return ra 5 thìk = k++;
cũng chok = 5;
hoá ra mình nhầm…Em cũng nghĩ bằng 6 nhưng sự thật là bằng 5 nhé các bác không tin thì cứ test thử trên c++ vs java đều thế. Chưa tìm ra lý do tại sao
Không cần cảm ơn nhé
int k=5;
k=k++;
ban đầu k=5 và giá trị k bên trái dấu gán của k=k++ sẽ =5 , tiếp theo k++ thì k tăng thêm 1 giá trị nên k trở thành 6.
Trong Java
Để làm rõ mình so sánh hai trường hợp, sự khác biệt ở đây là thời điểm giá trị được đẩy vào Stack (Push)
Case 1:
Case 2:
Nếu dấu Increment nằm sau (postfix) thì giá trị của biểu thức bên phải dấu bằng sẽ được đẩy vào stack rồi mới tăng, nên sự tăng ở đây vô nghĩa. Còn nếu ++ nằm trước (prefix) thì nó sẽ tăng rồi mới đẩy vào stack.
Stack ở đây là Operand stack, Operand stack nằm trong Frame, Frame thì nằm trong Stack.
Nếu bạn không hiểu stack là gì thì có thể hiểu quá trình trên như này:
Bạn à, mình cũng từng nghĩ như thế, cho đến khi chạy thử
Đã chụp hình Visual C++ ở trên
Cơ chế đấy là trong máy ảo JVM của Java. Còn C++ thì mình ko rõ. Những kết quả mình chạy vẫn là 5.
Hóng chuyên gia C++ vào giải đáp
Bác này nói chuẩn luôn nè!
Cái này được nói rất nhiều lần rồi, search trong forum cũng sẽ không ít topic nói về cái này.
Nó liên quan tới sequence point.
Một rule nhỏ cho C/C++ là ở mỗi sequence point, chỉ được cập nhật 1 biến 1 và 1 lần duy nhất, nếu không thì hành vi của nó sẽ không được xác định (Undefined Behavior)
k = k++ đã vô tình update biến k 2 lần (k++ và phép gán) ở trong cùng 1 sequence point. Và như ở trên, dẫn tới Undefined Behavior
http://c-faq.com/expr/seqpoints.html
Còn Java thì bạn Skyfall nói kỹ luôn rồi
Câu trả lời hay đây nè, bữa trước có lên stackoverflow cũng có nói như vậy
IDE cũng chỉ là 1 công cụ do con người tạo ra, nhiều khi quy ước khác nhau nên khi chạy trên mỗi IDE lại cho 1 kết quả khác nhau. Quan trọng là phải hiểu được lí thuyết của ngôn ngữ và cách hoạt động của IDE, chứ không phải cứ dịch chương trình xong thấy kết quả thì cho rằng luôn luôn đúng.
Undefinded behavior, kết quả không thể tính trước được
Mình hiểu điều đó. Nên mình muốn nhắc nhở những người giải thích như đinh đóng cột là
k == 5
hoặck == 6
rồi đưa dẫn chứng dài dằng dặc nửa trang giấy nên suy nghĩ kỹ hơn :))Mình chắc chắn là = 5 , một vài complier khác sẽ bằng 6