2013-02-10 22 views
6

thử nghiệm (c/cpp)Tại sao có nhiều gia số/giá trị hợp lệ trong C++ nhưng không có trong C?

#include <stdio.h> 

int main(int argc, char** argv) 
{ 
    int a = 0, b = 0; 
    printf("a = %d, b = %d\n", a, b); 
    b = (++a)--; 
    printf("a = %d, b = %d\n", a, b); 

    return 0; 
} 

Nếu tôi tiết kiệm ở trên như một tập tin cpp, nó biên dịch và kết quả này khi thực hiện:.

a = 0, b = 0 
a = 0, b = 1 

Tuy nhiên, nếu tôi lưu nó dưới dạng tệp .c, tôi nhận được lỗi sau:

test.c:7:12: error: lvalue required as decrement operator. 

Không nên thao tác (++a) trước (newValue)-- hoạt động? Có ai có bất cứ cái nhìn sâu sắc về điều này?

+4

'b = (++ a) -;' <- không phải là ** hành vi chưa xác định **? – LihO

+3

@LihO: Tại sao? Giá trị gia tăng trên 'a' được giải trình tự trước khi đánh giá –

+0

Tại sao không chỉ' b = a + 1' –

Trả lời

13

Trong C, kết quả của tiền tố và toán tử tăng/giảm hậu tố không phải là một lvalue.

Trong C++ kết quả của toán tử tăng/giảm hậu tố cũng không phải là một giá trị mà kết quả của toán tử tăng/giảm tiền tố là một giá trị lvalue.

Bây giờ, hãy làm điều gì đó như (++a)-- trong C++ là hành vi không xác định vì bạn đang sửa đổi giá trị đối tượng hai lần giữa hai điểm chuỗi.

EDIT: theo dõi trên @ bames53 nhận xét. Đó là hành vi không xác định trong C++ 98/C++ 03 nhưng những thay đổi trong C++ 11 trên ý tưởng về các điểm chuỗi bây giờ làm cho biểu thức này được định nghĩa.

+3

C++ 11 không xuất hiện với các điểm chuỗi và thay vào đó chỉ yêu cầu các lần đọc và sửa đổi phải được sắp xếp, chúng nằm trong '(++ a) -'. Xem [ở đây] (http://stackoverflow.com/q/10655290/365496) – bames53

+0

Không đồng ý với tuyên bố rằng '(++ a) -' được xác định rõ. Trang mà liên kết bames53 sẽ áp dụng cho '- (++ a)' nhưng post-increment không có cùng trình tự –

+0

@MM Các tác dụng phụ của '++ a' trong' (++ a) - ' được sắp xếp tương ứng với postfix '--' theo C++ 11, 5.17p1: *" Trong tất cả các trường hợp, phép gán được sắp xếp theo sau phép tính giá trị của toán hạng phải và trái, và trước khi tính giá trị của biểu thức gán . "* (với 5.3p2 *" Nếu x không thuộc loại bool, biểu thứC++ x tương đương với x + = 1 "*). – ouah

3

Trong C và C++, có các biểu thức giá trị có thể được sử dụng ở phía bên tay trái của toán tử = và các biểu thức giá trị có thể không được sử dụng. C++ cho phép nhiều thứ trở thành lvalues ​​vì ​​nó hỗ trợ ngữ nghĩa tham chiếu.

++ a = 3; /* makes sense in C++ but not in C. */ 

Toán tử tăng và giảm tương tự như gán, vì chúng thay đổi đối số của chúng.

Trong C++ 03, (++a)-- sẽ gây ra hành vi không xác định vì hai thao tác không được sắp xếp theo thứ tự tương ứng với nhau đang sửa đổi cùng một biến. (Mặc dù một là "trước" và một là "bài", họ là unsequenced vì không có ,, &&, ?, hay như vậy.)

Trong C++ 11, khái niệm hiện nay làm những gì bạn mong đợi . Nhưng C11 không thay đổi bất kỳ quy tắc nào như vậy, đó là lỗi cú pháp.

+0

"bởi vì nó hỗ trợ ngữ nghĩa tham chiếu" Nó đơn giản chỉ vì C không xác định các toán tử như kết quả trong các giá trị. – bames53

+0

@ bames53 Đó là phương tiện để kết thúc… – Potatoswatter

0

§5.2.7 Tăng và sụt lần:

The value of a postfix ++ expression is the value of its operand. [ ... ]  The operand shall be a modifiable lvalue.

Các lỗi mà bạn nhận được trong C biên dịch của bạn giúp gợi ý rằng đây chỉ là một tính năng có trong C++.

2

Đối với bất cứ ai có thể muốn các chi tiết chính xác về sự khác biệt khi chúng được nêu trong tiêu chuẩn, C99, §6.5.3/2 nói:

The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation.

Ngược lại, C++ 11, § 5.3.2/1 nói:

The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field.

[nhấn mạnh thêm, trong cả hai trường hợp]

Cũng lưu ý rằng mặc dù (++a)-- cho hành vi undefined (ít nhất là trong C++ 03) khi a là một int, nếu a là một số người dùng định nghĩa kiểu, vì vậy bạn đang sử dụng quá tải của riêng bạn ++--, hành vi sẽ được xác định - trong trường hợp này, bạn đang nhận được tương đương với:

a.operator++().operator--(0); 

Vì mỗi toán tử kết quả trong một cuộc gọi hàm (không thể chồng lên nhau) bạn thực sự do có các điểm trình tự để buộc hành vi được xác định (lưu ý rằng tôi không khuyến nghị sử dụng nó, chỉ lưu ý rằng hành vi này thực sự được xác định trong trường hợp này).

Các vấn đề liên quan