Tên của chức năng C ++ này là gì?


82

Tôi đang viết một số mã C ++ và bỏ qua nhầm tên của một hàm WSASocket. Tuy nhiên, trình biên dịch của tôi không phát sinh lỗi và liên kết của tôi SOCKETvới giá trị số nguyên 1 thay vì một ổ cắm hợp lệ.

Mã được đề cập nên trông như thế này:

this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Nhưng thay vào đó, nó trông như thế này:

this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Đến từ các ngôn ngữ khác, điều này có vẻ như nó có thể là một loại ẩn danh nào đó. Tên của đối tượng địa lý là gì, trong trường hợp nó thực sự là đối tượng địa lý?

Mục đích của nó là gì?

Thật khó để tìm kiếm nó, khi bạn không biết bắt đầu từ đâu.


3
+1, câu hỏi hay cho một câu đố trong quán rượu (hoặc một câu hỏi phỏng vấn kinh hoàng dành cho các công ty muốn thuê những người giỏi trêu ghẹo trí não).
Bathsheba

8
Liên kết đến bài viết trên Wikipedia về toán tử dấu phẩy . FWIW, một trong những cách sử dụng phổ biến là nhận được hai hiệu ứng phụ trong một forbiểu thức lặp * vòng lặp , ala for (int i = 0, j = 0; i <10; ++ i, --j) ... '
Tony Delroy

1
@ MichaelJ.Gray Về mặt kỹ thuật Bạn đã nhầm. Nó không ghi đè hành vi. Imagin: i=0;j=0;x=i++,j=6;x và j sẽ là 6 và tôi vẫn là 1. Nếu hành vi của i ++ bị ghi đè, nó sẽ vẫn là 0. Nhưng mỗi câu lệnh được gọi và sau khi đạt đến ,tất cả các phần mở rộng sẽ bị loại bỏ và điểm trình tự giả tiếp theo được gọi. Vì vậy, phần đầu tiên =chỉ gán phần sau phần cuối cùng ,nhưng mỗi điểm sẽ được gọi. Dù sao: Tôi không hiểu tại sao biên dịch của bạn không cảnh báo bạn về xác định lại chức năng khai báo và thay vào đó thay đổi mã của bạn để một cái gì đó về hành vi khác nhau
dhein

5
Nếu bạn sử dụng một trình biên dịch thích hợp, với cảnh báo bật, nó sẽ cảnh báo về mã tinh ranh như vậy, ví dụ gccg++với -Walltùy chọn nói:warning: left-hand operand of comma expression has no effect [-Wunused-value]
Sam Watkins

3
Vì vậy, theo tôi câu trả lời tốt nhất cho câu hỏi này là "luôn bật cảnh báo" - sau đó chính trình biên dịch sẽ giải thích rằng có lỗi và cho bạn biết bạn đã làm gì; và câu trả lời này cũng sẽ giải quyết nhiều vấn đề khác cho bạn.
Sam Watkins

Câu trả lời:


151

Toán tử dấu phẩy † đánh giá phía bên trái, loại bỏ giá trị của nó và kết quả là cho phía bên phải. WSA_FLAG_OVERLAPPEDlà 1, và đó là kết quả của biểu thức; tất cả các giá trị khác bị loại bỏ. Không có ổ cắm nào được tạo.


† Trừ khi quá tải. Có, nó có thể bị quá tải. Không, bạn không nên quá tải nó. Bước ra khỏi bàn phím, ngay bây giờ!


9
+1, tăng cường tinh thần rất hiệu quả làm quá tải toán tử dấu phẩy, nhưng đó là một ngoại lệ rất đơn độc đối với quy tắc: không làm điều đó .
Bathsheba

2
@Bathsheba Boost.Assign cũng nạp chồng toán tử dấu phẩy, nhưng ai sử dụng điều đó kể từ C ++ 11?
rubenvb

39
Nhưng bạn đã có lời giải thích tốt nhất về mức độ đáng sợ của dấu phẩy. Không thể tha thứ và đầy chế giễu, nó đã cản trở mã của tôi trong vài phút trong khi nhìn chằm chằm vào tôi mà không hề xấu hổ vì hành vi của nó.
Michael J. Grey,


1
@ R.MartinhoFernandes - Eigen cũng nạp chồng toán tử dấu phẩy rất hiệu quả. Xem câu hỏi SE này để biết một số cách sử dụng mẫu.
David Hammen,

22

Các nhà điều hành dấu phẩy là làm cho ý nghĩa của mã của bạn.

Bạn đang thiết lập hiệu quả this->listener = WSA_FLAG_OVERLAPPED;điều này chỉ xảy ra là hợp lệ về mặt cú pháp.


3
Không chỉ hợp lệ về mặt cú pháp, mà vì API Windows không phải là loại an toàn nên nó cũng là một chuyển đổi hợp lệ.
MSalters

5
@MSalters không phải là POSIX tốt hơn nhiều về mặt đó
chbaker0

1
Đó là lý do tại sao các hàm tạo có thể gọi với một đối số duy nhất phải rõ ràng , sau đó lỗi trình biên dịch sẽ xảy ra và nhà phát triển sẽ có cơ hội xem xét lại cấu trúc kỳ lạ này.
Matthieu M.

@MSalters Chà, SOCKETlà một typedef cho unsigned int, và WSA_FLAG_OVERLAPPEDlà một intnghĩa đen. Nếu nó SOCKETlà một từ đồng nghĩa int, nó thậm chí sẽ không phải là một chuyển đổi .
Joker_vD

1
@Joker_vD: Thật vậy. Nếu họ biến nó thành một typedef struct __socket*, chúng tôi sẽ có ít lỗi hơn. Nhưng chỉ có quá nhiều mã ngoài đó mà "biết" SOCKETlà không thể thiếu.
MSalters

21

Trình biên dịch đang đánh giá lần lượt từng điểm trình tự trong ngoặc và kết quả là biểu thức cuối cùng, WSA_FLAG_OVERLAPPEDtrong biểu thức.

Toán tử dấu phẩy ,là một điểm trình tự trong C ++. Biểu thức ở bên trái dấu phẩy được đánh giá đầy đủ trước khi biểu thức ở bên phải là. Kết quả luôn là giá trị ở bên phải. Khi bạn có biểu thức có dạng (x1, x2, x3, ..., xn) thì kết quả của biểu thức luôn là xn.


Sau khi bạn thêm phần làm rõ của mình vào đó, điều đó có ý nghĩa hơn. Lúc đầu, tôi không hiểu rõ về sự liên quan của vấn đề điểm trình tự.
Michael J. Gray,
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.