2011-01-08 42 views
12

Hãy xem xét câu lệnh sau. Giá trị được lưu trữ trong b là bao nhiêu?sử dụng toán tử có điều kiện

int a=1; 
int b = a+=1 ? a+=1 : 10; 

Tôi nhận câu trả lời là 4. Bất kỳ ai cũng có thể giải thích cách hoạt động.

+7

Hành vi không xác định. – GWW

+1

@GWW: Không !! [....] –

+3

"Bất kỳ ai cũng có thể giải thích cách hoạt động của bạn". >> Tôi chắc chắn không thể, yêu cầu các lập trình viên đã viết nó. Và đừng bao giờ yêu cầu anh ta viết lại bất cứ điều gì. :) – Mehrdad

Trả lời

14

Nó phải làm với ưu tiên. Nếu bạn kiểm tra đoạn mã sau (với bìa phải a+=1 thay đổi cho đơn giản):

#include <iostream> 

int main (void) { 
    int a=1; 
    int b = a+=1 ? 7 : 10; 
    std::cout << b << std::endl; 
    return 0; 
} 

bạn sẽ thấy rằng sản lượng là 8, không 7 hoặc 10.

Đó là bởi vì các tuyên bố:

int b = a+=1 ? 7 : 10; 

đang được hiểu là:

int b = (a += (1 ? 7 : 10)); 

Bây giờ, áp dụng đến trường hợp của bạn, chúng tôi nhận được:

int b = (a += (1 ? a += 1 : 10)); 

và, theo thứ tự thực hiện:

  • tận cùng bên phải a += 1 (kể từ 1 là đúng) đặt a thành 2.
  • tận cùng bên trái a += 2 (2 là kết quả của bước trước) đặt a đến 4.
  • b = 4 (4 là kết quả của bước trước đó).

Chỉ cần nhớ rằng bạn không nhất thiết phải dựa vào thứ tự đánh giá đó. Mặc dù có một điểm chuỗi tại số ? (để 1 được đánh giá đầy đủ trước khi tiếp tục), không có điểm chuỗi giữa cực bên phải a += ... và tận cùng bên trái a += .... Và sửa đổi một biến duy nhất hai lần mà không có một điểm chuỗi can thiệp là hành vi không xác định, đó là lý do gcc -Wall sẽ cung cấp cho bạn thông điệp rất hữu ích:

warning: operation on ‘a’ may be undefined 

Đó thực tế là nó cung cấp cho bạn 4 là trùng hợp ngẫu nhiên thuần túy. Nó có thể chỉ là một cách dễ dàng cung cấp cho bạn 3, 65535 hoặc thậm chí định dạng đĩa cứng của bạn để dạy cho bạn một bài học :-) phân tích

+0

@shreedhar: Có, tôi đã xóa nhận xét của mình. Câu trả lời này có vẻ đúng. –

+0

BTW g ++ cho tôi một cảnh báo "thao tác trên' a' có thể không xác định ". –

+1

@Prasoon: Đó là vì 'a + = a + = 1' không xác định. – ephemient

2

hội: Mã

int main() 
{ 
    int a=1; 
    int b = a+=1 ? a+=1 : 10; 
    return 0; 
} 

hội được tạo ra (sử dụng MinGW) cho đoạn code trên là được hiển thị bên dưới. Các ý kiến ​​là của tôi, tất nhiên! Đọc các bình luận cũng!

call ___main  //entering into main() 
movl $1, 12(%esp) //int a = 1; means 12(%esp) represents a; 
incl 12(%esp)  //a+=1 ; a becomes 2 
movl 12(%esp), %eax //loading 'a' onto a register(eax); eax becomes 2 
addl %eax, %eax  //adding the register to itself; eax becomes 4 
movl %eax, 12(%esp) //updating 'a' with the value of eax; 'a' becomes 4 
movl 12(%esp), %eax //this step could be optimized away; anyway it loads value of 'a' onto the register(eax); eax becomes 4, in fact even earlier it was 4 too! needless step! 
movl %eax, 8(%esp) //loading the value of eax at another memory location which is 8(%esp); this location represents b; 
movl $0, %eax  //making eax zero! the return value of main()! 
leave    //now main() says, please leave me! 

12(%esp) miêu tả vị trí bộ nhớ của a, và ở một byte khoảng cách 4 từ nó, có nghĩa là, 8(%esp) đại diện b. Cuối cùng, giá trị ở cả hai vị trí bộ nhớ này là 4.

Do đó, b = 4. Ngoài ra a = 4.

6

Như đã nêu trong câu trả lời khác hai đoạn mã tương đương do các quy tắc ngữ pháp của C++ mà xác định cách biểu hợp chất phải được phân tích.

int a=1; 
int b = a+=1 ? a+=1 : 10; 

int a=1; 
int b = (a += (1 ? (a += 1) : 10)); 

Mặc dù có một điểm chuỗi trong một có điều kiện thể hiện nó là giữa việc đánh giá các biểu hiện đầu tiên (1) và việc đánh giá bất cứ một trong những thứ hai và biểu thức thứ ba được đánh giá (a += 1 trong trường hợp này). Không có điểm chuỗi phụ rõ ràng sau khi đánh giá biểu thức thứ hai hoặc thứ ba.

Điều này có nghĩa rằng a được sửa đổi hai lần trong initializer cho b mà không có một điểm chuỗi can thiệp để mã có hành vi undefined.

+0

Đây là câu trả lời đúng. Tốt bắt Charles. :) +1 –

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