Hành vi khác nhau của toán tử dấu phẩy trong C ++ với trả về?


83

Điều này (lưu ý toán tử dấu phẩy ):

#include <iostream>
int main() {
    int x;
    x = 2, 3;
    std::cout << x << "\n";
    return 0;
}

kết quả đầu ra 2 .

Tuy nhiên, nếu bạn sử dụng returnvới toán tử dấu phẩy, điều này:

#include <iostream>
int f() { return 2, 3; }
int main() {
    int x;
    x = f();
    std::cout << x << "\n";
    return 0;
}

kết quả đầu ra 3 .

Tại sao toán tử dấu phẩy hoạt động khác với return?


Câu trả lời:


140

Theo Mức độ ưu tiên của toán tử , toán tử dấu phẩy có mức độ ưu tiên thấp hơn operator=, do đó, x = 2,3;tương đương với (x = 2),3;. (Mức độ ưu tiên của toán tử xác định cách toán tử sẽ bị ràng buộc với các đối số của nó, chặt hơn hoặc lỏng hơn so với các toán tử khác theo các ưu tiên của chúng.)

Lưu ý rằng biểu thức dấu phẩy (x = 2),3ở đây, không phải 2,3. x = 2được đánh giá lúc đầu (và các tác dụng phụ của nó được hoàn thành), sau đó kết quả bị loại bỏ, sau đó 3được đánh giá (trên thực tế nó không làm gì cả). Đó là lý do tại sao giá trị của x2. Lưu ý rằng đó 3là kết quả của toàn bộ biểu thức dấu phẩy (tức là x = 2,3), nó sẽ không được sử dụng để gán cho x. (Thay đổi nó thành x = (2,3);, xsẽ được chỉ định với 3.)

Đối với return 2,3;, khái niệm dấu phẩy là 2,3, 2được đánh giá thì kết quả của nó được loại bỏ, và sau đó 3được đánh giá và trở về như là kết quả của biểu thức dấu phẩy toàn bộ, mà được trả về bởi lệnh return sau.


Thông tin bổ sung về Biểu thứcTuyên bố

Một biểu thức là một chuỗi các toán tử và toán hạng của chúng, chỉ định một phép tính.

x = 2,3;câu lệnh biểu thức , x = 2,3là biểu thức ở đây.

Biểu thức được theo sau bởi dấu chấm phẩy là một câu lệnh.

Cú pháp: attr(optional) expression(optional) ; (1)

return 2,3;câu lệnh nhảy ( câu lệnh trả về ), 2,3là biểu thức ở đây.

Cú pháp: attr(optional) return expression(optional) ; (1)


1
lời giải thích hay. Nhưng có một số ứng dụng thực tế? hay chỉ là những lỗi cần thực hiện?
Jean-François Fabre

7
@ Jean-FrançoisFabre IMO nó chỉ là khó hiểu, không hữu ích chút nào.
songyuanyao

11
Tôi đã thấy nó một hoặc hai lần được sử dụng trong forcác vòng lặp, kỳ lạ thay, nó có thể làm cho mã rõ ràng hơn trong các phép tính số.
Bathsheba

6
@ Jean-FrançoisFabre: như Bathesheba nói, đó là để bạn có thể viết một cái gì đó giống như i += 1, j += 2trong vòng lặp for. Ai đó đã quyết định rằng ngữ pháp C ++ (hay đúng hơn là ngữ pháp C, vì phần này đã được sao chép từ đó) đã đủ phức tạp mà không cố gắng xác định rằng mức độ ưu tiên của dấu phẩy cao hơn phép gán khi bạn viết x = 2, 3nhưng thấp hơn khi bạn viết x = 2, y = 3!
Steve Jessop

1
@Holger: Dấu chấm phẩy kết thúc một câu lệnh, nó không phải là một toán tử. Đây là điều mà câu trả lời có thể được điều chỉnh để làm rõ hơn. "x = 2, 3" là một biểu thức có 2 toán tử và vì lý do hỗ trợ cho (;;), = có mức độ ưu tiên cao hơn. (Như mọi người đã nói.) Nhưng "return 2, 3;" là một câu lệnh có chứa biểu thức "2, 3". Về mặt kỹ thuật , từ khóa "trở lại" không được ưu tiên. (Mặc dù có hiệu quả , vì nó là một phần của tuyên bố chấp nhận sự biểu hiện, nó được phân tách cuối cùng - giảm "ưu tiên" hơn bất kỳ nhà điều hành trong biểu thức.)
Micha Berger

32

Toán tử dấu phẩy (còn được gọi là phép phân tách biểu thức ) được đánh giá từ trái sang phải. Vì vậy, return 2,3;tương đương với return 3;.

Việc đánh giá x = 2,3;(x = 2), 3;do sự ưu tiên của người vận hành . Đánh giá vẫn từ trái sang phải và toàn bộ biểu thức có giá trị 3 với tác dụng phụ của việc xgiả sử giá trị là 2.


2
Bạn vui lòng chỉnh sửa và nói rõ hơn về toán tử tách biểu thức được không? Giống như tôi đã đề cập trong một bình luận về câu trả lời của @ songyuanyao, tôi có thể hiểu tại sao return 2,3return (2,3)cũng giống như vậy. Tôi tin rằng trước đây nên được (return 2),3.
xyz

@BiagioFesta giải thích rõ phần đó.
Bathsheba

1
@ prakharsingh95 return 2là một câu lệnh (chẳng hạn như những câu được tạo bởi for,while,if), không phải là một biểu thức. Bạn không thể viết vd f(return 2)hoặc 2+return 2. Vì vậy, (return 2),3là cú pháp không hợp lệ.
chi

@chi Vâng, bạn nói đúng. Ý tôi là tôi đã mong đợi return 2, 3được hiểu(return 2), 3.
xyz

2
@ prakharsingh95 theo ngữ pháp của C ++, returnchỉ có thể xảy ra trong các trường hợp sau: (a) return expression_opt ; , và (b) return Braced-init-list ; .
MM

20

Tuyên bố này:

  x = 2,3;

được cấu tạo bởi hai biểu thức :

> x = 2
> 3

toán tử ưu tiên , =có nhiều ưu tiên hơn dấu phẩy ,, do đó, x = 2được đánh giá và đứng sau 3 . Sau đó, xsẽ bằng 2.


Trong returnthay vì:

int f(){ return 2,3; }

Cú pháp ngôn ngữ là:

return <expression>

Lưu ý return không phải là một phần của biểu thức.

Vì vậy, trong trường hợp đó, hai biểu thức sẽ được đánh giá sẽ là:

> 2
> 3

Nhưng chỉ dấu ( 3) thứ hai sẽ được trả về.


2
UV'd. Rất cầu kỳ, nhưng sẽ rất hay nếu bạn đánh dấu <expression>là tùy chọn rõ ràng (từ góc độ ngữ pháp).
Bathsheba

2
Có 5 biểu thức trong cây phân tích cú pháp của x=2,3. Cả hai nghĩa đen 23đều nằm ở cuối cây phân tích cú pháp, cũng như mã định danh x. Đây là tất cả các biểu thức hợp lệ riêng. Mức độ ưu tiên của toán tử có nghĩa là nó =xuất hiện thấp hơn trong cây phân tích cú pháp và kết hợp hai biểu thức x2thành biểu thức thứ tư x=2. Cuối cùng, biểu thức thứ năm được hình thành bởi toán tử dấu phẩy nối hai vế của nó x=23. Tuy nhiên, bạn nêu sai rằng ưu tiên toán tử xác định thứ tự đánh giá. Nó không. Thứ tự đánh giá được xác định bởi các quy tắc trình tự.
MSalters

2
Tôi đã bỏ phiếu cho việc đề cập rằng sự trở lại không phải là một phần của một biểu thức
Daniel Jour

@MSalters Tôi đồng ý với bạn, nhưng tôi chỉ sử dụng sai từ " bởi vì ", thay vì " kể từ ". Có điều tiếng Anh của tôi không quá hoàn hảo! ; - =
Biagio Festa

2
Ở đây có phải "biểu thức vĩ mô" là một thuật ngữ kỹ thuật không? Có vẻ hơi khó hiểu khi sử dụng nó khi "biểu thức macro" theo nghĩa của nội dung tiền xử lý cũng tồn tại.
senshin

2

Cố gắng áp dụng cách tiếp cận đơn giản chỉ làm nổi bật mức độ ưu tiên bằng dấu ngoặc đơn:

( x = 2 ), 3;

return ( 2, 3 );

Bây giờ chúng ta có thể thấy toán tử nhị phân "," hoạt động theo cùng một cách trên cả hai, từ trái sang phải.


1
Phần khó khăn là nhận ra rằng x = 2, 3bản thân nó là một biểu thức, trong khi đối với returnreturn <expression>. Vì vậy, bạn đọc chúng như (x = 2, 3)(2, 3).
xyz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.