Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 14 kết quả

Đề tài: Nhiều phép tính giữa các biến trong một lệnh nghĩa là gì?

  1. #1
    Ngày gia nhập
    09 2011
    Bài viết
    3

    Mặc định Nhiều phép tính giữa các biến trong một lệnh nghĩa là gì?

    Hiện mình đang thắc mắc cách tính trong C như thế nào :
    Mình có :
    x=10
    y=11
    vậy
    printf("\n\n%6d\n%6d\n%6d",x--*++y,x-- - --y,x++ + ++y); //kq 120,0,22


    printf("\n%d",x-- * ++y); //kq=120
    printf("\n%d",x-- - ++y); //kq=-2
    printf("\n%d",x++ + ++y); //kq=20

    Cách tính ra sao.Đó là thắc mắc của mình mà mình nghĩ nhiều người học xong chắc cũng quên nên hỏi luôn dùm các bạn í

  2. #2
    Ngày gia nhập
    11 2010
    Bài viết
    589

    Cái này mỗi trình dịch mỗi hệ điều hành nó dịch một kiểu cho nên bạn không cần thiết và không nên nhớ mấy cái này. Đồng thời khi lập trình phải tránh những phép tính như thế, thứ nhất là không biết sẽ ra kiểu gì, thứ 2 là phức tạp khó đọc.

  3. #3
    Ngày gia nhập
    04 2010
    Nơi ở
    Recycle Bin
    Bài viết
    358

    printf("\n\n%6d\n%6d\n%6d",x--*++y,x-- - --y,x++ + ++y); //kq 120,0,22
    toán tử tiền tố ++, -- sẽ tăng, giảm giá trị biến trước khi dùng vào biểu thức.
    toán tử hậu tố ++, -- sẽ tăng, giảm giá trị biến sau khi dùng vào biểu thức.
    ta có thể tách (x--*++y,x-- - --y,x++ + ++y) riêng để tính, độ ưu tiên từ phải qua trái. Nghĩa là R - G - B
    Bạn có thể kiếm chứng điều này bằng cách thêm x-- vào cuối hàm printf. Như sau
    printf("\n\n%6d\n%6d\n%6d",x--*++y,x-- - --y,x++ + ++y,x--); //kq 108,-1,21
    Thêm 1 ví dụ rất thú vị
    printf("\n%6d",(x--*++y,x-- - --y,x++ + ++y)); //kq 20
    Độ ưu tiên biểu thức trong ngoặc từ trái qua phải, và biểu thức cuối cùng trong ngoặc được in ra. Hoàn toàn ngược lại với lệnh printf trên kia

    NÊN lưu ý:
    1. Những biểu thức như trên là không nên, vì dễ gây nhầm lẫn kể cả những người lập trình lâu năm. Ta cần tính đến độ ưu tiên các toán tử, phép toán, và cả lệnh printf cũng ảnh hưởng đến kết quả
    2. Ta không nên viết biểu thức kiểu đó. Viết rõ ràng ý tưởng của mình, cái nào ưu tiên để trong ngoặc, dùng biến tạm lưu kết quả trước khi viết lệnh printf.
    Đã được chỉnh sửa lần cuối bởi conrongchautien : 20-02-2012 lúc 02:09 AM.
    YH : lobuocphuudu_218
    Phone : 0126 463 5095

    http://forums.congdongcviet.com/signaturepics/sigpic55872_2.gif

  4. #4
    Ngày gia nhập
    04 2010
    Bài viết
    1,534

    Khi đặt ra ngôn ngữ C, tác giả cố ý tối giản số ký hiệu và từ khóa. Vì vậy các ký hiệu toán tử và từ khóa trong C có ý nghĩa tùy theo ngữ cảnh.

    Khi viết

    (x--*++y, x-- - --y, x++ + ++y)

    thì những dấu phẩy là toán tử có nhiệm vụ ngăn/tách (sequencing) biểu thức chính thành những biểu thức con. Và những biểu thức con sẽ được tính từ trái sang phải. Biểu thức con ở bên phải dấu phẩy sau cùng sẽ được thực hiện cuối cùng và trị của nó sẽ là trị của toàn lệnh.

    Khi viết

    printf("\n\n%6d\n%6d\n%6d", x--*++y, x-- - --y, x++ + ++y);

    thì những dấu phẩy chỉ là những dấu ngăn (delimiters) các tham số cho hàm printf.
    Tiêu chuẩn C không bắt buộc phải tính biểu thức tham số nào trước cho nên kết quả không thể xác định.
    Thường thì trình dịch dùng stack để chép tham số nên ta thường thấy nó tính từ phải sang trái - tuy nhiên, nhắc lại, hoàn toàn không bắt buộc.

    Những ví dụ của bạn đem qua máy khác, dùng trình dịch khác chưa chắc kết quả sẽ ra giống vậy.

  5. #5
    Ngày gia nhập
    07 2010
    Nơi ở
    chỗ kín
    Bài viết
    446

    lôi dấu ',' và thứ tự truyền tham số từ trái sang phải hay từ phải sang trái vào đây là sai lầm, nếu mình nhớ ko nhầm thì giải thích trên msdn cũng mắc phải lỗi này.
    Việc ép trình dịch vào đây thì càng sai lầm nữa, cứ theo chuẩn của C mà làm.

    dấu , có độ ưu tiên cuối cùng,

    cách tính biểu thức print trên:

    để đơn giản, lấy ví dụ nhỏ thôi

    x =1;
    y=1;
    printf("...", x++,x--*++y,++x)

    ta cứ làm từ trái sang phải đi, (vì đằng nào làm từ phải qua trái cũng cho kq tương tự).
    x++ : trả về x, tăng x lên 1 sau lệnh printf (1)
    x-- : trả về x, giảm x đi 1 sau lệnh printf (2)
    ++y: tăng y và trả về y (3)
    ++x: tăng x và trả về x (4)

    vậy sau khi đi một lượt, ta có

    nên nhớ , x++: trả về x, sau đó mới tăng, chứ không phải trả về giá trị của x sau đó mới tăng.
    printf("...", x, x*y, x);
    x bây giờ bằng 2 vì (4)
    -> lệnh printf tương đương với
    printf("...",2,2*2,2)

    sau lệnh printf, x, y bằng 2.

  6. #6
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Mặc định Nhiều phép tính giữa các biến trong một lệnh nghĩa là gì?

    @ptkhanh: Các bạn bên trên đã giải thích rõ ràng rồi, bạn đừng nhầm lẫn giữa dấu phẩy của operator, và dấu phẩy ngăn cách cách tham số khi gọi hàm - 2 cái đó là hoàn toàn khác nhau.

    Không có tiêu chuẩn nào quy định các tham số khi gọi hàm sẽ được evaluate theo thứ tự nào. Vì vậy cũng không cần mất thời gian tính xem cái nào sẽ chạy trước cái nào chạy sau, kết quả ra bao nhiêu... mà chỉ đơn giản là: Cần tuyệt đối tránh kiểu gọi hàm mập mờ như vậy. Nếu cần cứ gán qua các biến trung gian.

  7. #7
    Ngày gia nhập
    04 2010
    Bài viết
    1,534

    Trích dẫn Nguyên bản được gửi bởi pkthanh92 Xem bài viết
    lôi dấu ',' và thứ tự truyền tham số từ trái sang phải hay từ phải sang trái vào đây là sai lầm, nếu mình nhớ ko nhầm thì giải thích trên msdn cũng mắc phải lỗi này.
    Việc ép trình dịch vào đây thì càng sai lầm nữa, cứ theo chuẩn của C mà làm.

    dấu , có độ ưu tiên cuối cùng,

    cách tính biểu thức print trên:

    để đơn giản, lấy ví dụ nhỏ thôi

    x =1;
    y=1;
    printf("...", x++,x--*++y,++x)

    ta cứ làm từ trái sang phải đi, (vì đằng nào làm từ phải qua trái cũng cho kq tương tự).
    x++ : trả về x, tăng x lên 1 sau lệnh printf (1)
    x-- : trả về x, giảm x đi 1 sau lệnh printf (2)
    ++y: tăng y và trả về y (3)
    ++x: tăng x và trả về x (4)

    vậy sau khi đi một lượt, ta có

    nên nhớ , x++: trả về x, sau đó mới tăng, chứ không phải trả về giá trị của x sau đó mới tăng.
    printf("...", x, x*y, x);
    x bây giờ bằng 2 vì (4)
    -> lệnh printf tương đương với
    printf("...",2,2*2,2)

    sau lệnh printf, x, y bằng 2.
    Trật lất:

    Theo C99, trong mục "6.5.2.2 Function Calls," dòng thứ 10: "The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified..."

    Tiêu chuẩn C cũng định nghĩa trạng thái không xác định được như sau:
    unspecified behavior
    use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance

    EXAMPLE An example of unspecified behavior is the order in which the arguments to a function are evaluated.[/quote]

  8. #8
    Ngày gia nhập
    07 2010
    Nơi ở
    chỗ kín
    Bài viết
    446

    haizz, bác đọc câu này chưa

    "ta cứ làm từ trái sang phải đi, (vì đằng nào làm từ phải qua trái cũng cho kq tương tự)."

    nếu một biểu thức cho 2 kết quả thì có thể khẳng định chuẩn đó là chuẩn "tàu".
    Việc đánh giá từ trái sang phải hay từ phải sang trái, chuẩn không bắt buộc, vì làm kiểu gì mà chẳng ra cùng kết quả.

    chuẩn ở trên em nói là chuẩn "thứ tự ưu tiên các biểu thức", phép * trước phép +, phép + trước phép ',', việc đánh giá biểu thức trên không phụ thuộc vào mục 6.5.2.2 của C99, bác nên nhìn nhận kỹ lại vấn đề.

  9. #9
    Ngày gia nhập
    11 2010
    Bài viết
    589

    Trích dẫn Nguyên bản được gửi bởi pkthanh92 Xem bài viết
    haizz, bác đọc câu này chưa

    "ta cứ làm từ trái sang phải đi, (vì đằng nào làm từ phải qua trái cũng cho kq tương tự)."

    nếu một biểu thức cho 2 kết quả thì có thể khẳng định chuẩn đó là chuẩn "tàu".
    Việc đánh giá từ trái sang phải hay từ phải sang trái, chuẩn không bắt buộc, vì làm kiểu gì mà chẳng ra cùng kết quả.
    Sai lầm. Có rất nhiều trường hợp thứ tự thực hiện ảnh hưởng tới kết quả. VD, xét một lời gọi hàm:
    x = 1.
    F(x*x, --x);
    Nếu thực hiện từ phải sang thì nó là F(0,0)
    Nếu thực hiện từ trái sang thì nó là F(1,0)

  10. #10
    Ngày gia nhập
    04 2010
    Nơi ở
    Recycle Bin
    Bài viết
    358

    Tớ nghĩ đây cũng là 1 vấn đề cần xem xét dưới góc độ học thuật. Giả như có 1 bài trắc nghiệm thế này dĩ nhiên ta cũng phải có đáp án cụ thể.
    Có bạn nói rằng: " thứ tự là không quan trọng" hãy cứ xem lại VD của chủ thớt!!!
    Tớ đã kiểm tra bằng cách chạy chương trình trên các công cụ lập trình c khác nhau và cho cùng kết quả như đã nói trên. Điều này chính là chuẩn nếu như lý thuyết không đề cập đến
    YH : lobuocphuudu_218
    Phone : 0126 463 5095

    http://forums.congdongcviet.com/signaturepics/sigpic55872_2.gif

Các đề tài tương tự

  1. Kỹ thuật C++ Địa chỉ các biến trong C++, 0x có ý nghĩa gì?
    Gửi bởi mvmanh trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 03-07-2011, 08:54 PM
  2. nhận nhiều biến trong 1 hàm = va_list
    Gửi bởi alisson trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 7
    Bài viết cuối: 05-06-2011, 03:06 PM
  3. Lập trình C Cách tạo ra nhiều biến chuỗi 1 lúc trong C?
    Gửi bởi lenguyenvt trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 8
    Bài viết cuối: 26-03-2011, 02:47 PM
  4. khai báo biến toàn cục trong file .h để sử dụng nhiều nơi?
    Gửi bởi alisson trong diễn đàn Thắc mắc lập trình Visual C++
    Trả lời: 6
    Bài viết cuối: 15-02-2011, 02:27 PM
  5. Biến cục bộ được định nghĩa hoàn toàn trong .NET v3.5
    Gửi bởi nhc1987 trong diễn đàn Tutorials và Thủ thuật lập trình C#, ASP.NET
    Trả lời: 0
    Bài viết cuối: 05-02-2008, 01:41 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn