30/09/2018, 17:33
Thảo luận về ví dụ với toán tử ++ trong C
Em có thử chạy chương trình sau trên hai trình biên dịch khác nhau là VS2013 trên Win 7 và gcc trên Ubuntu và cho ra hai kết quả khác nhau. Các bác cùng thử thảo luận xem vì sao lại có kết quả như thế nhé:
#include "stdio.h"
void main()
{
int i = 5, j = 5, y;
int x = (++i) + (++i) + (++i);
y = (++j) + (++j) + (++j);
printf("x = %d, y = %d, i = %d, j = %d
", x, y , i, j);
}
Kết quả:
Trên VS2013: x = 24, y =24, i = 8, j = 8
Trên Ubuntu: x = 22, y =22, i = 8, j = 8
Bài liên quan
Cái này gọi là Undefined Behavior.
Tức tùy vào trình biên dịch thì nó sẽ cho ra kết quả khác nhau.
Bác có thể nói rõ hơn được không? Cách tính của hai trình biên dịch kia như thế nào mà lại ra được kết quả như thế bác?
Theo mình thì rất có thể do cách tính của biếu thức dưới dạng ký pháp Balan. Như vậy, với compiler VS2013 thì biểu thức hậu tố được viết dưới dạng (++i)(++i)(++i)++ còn với compiler GCC (ubuntu) thì sẽ có dạng (++i)(++i)+(++i)+.
Vì theo thứ tự tính toán phép ++ sẽ thực hiện trước phép + nên với VS2013 thì phép ++i sẽ được tính 3 lần liên tục vì thế i = 8 và tổng sẽ là 24. Còn với GCC thì hai phép ++ đầu được thực hiện sau đó thực hiện phép + thứ nhất được tổng là 14 và cộng với phép cộng thứ hai với ++i lúc này bằng 8 nên được kết quả là 14+8 = 22.
Theo mình là như trên, để mình tìm hiểu kĩ lại và có câu trả lời thích đáng sau nhé!
Muốn giải thích nó tại sao lại ra kq như vậy thì phải xem mã assembler nó sinh ra thôi. Nói chung undefined behavior này không tiên đoán dc kết quả. Tốt nhất là tránh nó
Bác biết cách xuất ra mã assembly không thử xuất ra xem cách xử lý của compiler cho em và những bạn muốn biết hiểu với được không ạ
E là compiler tính theo cách khác bác ạ
Nếu mà linux thì dùng lệnh gcc -S [file name] -o [file out].s sau đó có thể xem mã asm. Nói chung cái này mình cũng không rành lắm, thử hỏi anh @ltd xem
Mình lưu ý chút là compiler không tính toán gì cả nhé, chỉ chuyển từ ngôn ngữ bậc cao xuông ngôn ngữ bậc thấp hơn và việc chuyển một biểu thức phải sử dụng một thuật toán hay phương pháp nào đó (ở đây mình chỉ biết biểu thức hậu tố thôi).
Window thì cứ down ollydbg về load file là đọc được ngay.
Còn linux thì mình chịu.
Bây giờ chỉ còn vấn đề là bạn hiểu hay ko Do asm ko như C đâu nhé
của mình chạy trên windows, dùng gcc để biên dịch.rồi disassemble bằng gdb.
chạy chương trình được
x = 22, y = 22, i = 8, j = 8
đoạn phía trên là của biến y. do i cộng thêm 1 2 lần (giờ i=7), sau đó edx=eax+eax=14, tiếp theo tăng lên 1 được (i=8). ta có 7+7+8=22
còn bên VS thì mình nghĩ nó sẽ cộng hết một lượt nên mới được 24.