2011-02-05 34 views
7

thể trùng lặp:
Double Negation in C++ code.Mục đích của âm kép trong định nghĩa macro, như (!! (expr)) là gì?

Tôi đang đọc một cơ sở mã, và tìm thấy một cái gì đó như thế này:

#define uassert(msgid, msg, expr) (void)((!!(expr))||(uasserted(msgid, msg), 0)) 

Tôi không thể hiểu tại sao (!! (expr)) được sử dụng thay vì một đơn (expr). Dù sao, một tiêu cực đôi có nghĩa là tích cực, phải không? Tui bỏ lỡ điều gì vậy?

+0

Tôi thậm chí không thể tìm ra mục đích của mã này là gì! ;) – BlackBear

+0

Giống như R nói, nó hoàn toàn vô dụng ở đây. – GManNickG

+0

nó dư thừa trong trường hợp này như bản thân bạn đã chỉ ra một cách chính xác. Có lẽ nó chỉ được thêm vào để tránh một số cảnh báo trình biên dịch. –

Trả lời

6

Đó là cách để chuyển biểu thức thành bool. Tuy nhiên, trong C++, toán tử! có thể bị quá tải. Một cách khác cho C/C++:

C++ cách duy nhất:

static_cast<bool>(expr) 

[Chỉnh sửa] Suy nghĩ thêm về C++ điều hành quá tải, nó làm cho tinh thần để tránh sử dụng khai thác. Các thư viện như Boost.Spirit và Boost.Lambda sử dụng các mẫu biểu thức và đánh giá lười biếng, do đó các biểu thức như (expr) || call() có thể hoạt động không như mong muốn. Phiên bản bằng chứng đạn đầu tiên của macro đó trông giống như sau:

#define uassert(expr) if(expr) {} else { uasserted(...); } 

Ở đây, chỉ chuyển đổi expr thành bool được sử dụng. Cần có chi nhánh else để bảo vệ khỏi các biểu thức như uassert(x) else something_else();.

+0

Chấp nhận câu trả lời này, vì @Maxim đã đưa ra cả lời giải thích và kiến ​​thức sâu hơn. – fzhang

+1

Và bây giờ 'uassert (expr)' không còn là một biểu thức; đó là một tuyên bố. Điều này hạn chế rất nhiều nơi bạn có thể sử dụng nó.Nếu bạn muốn chuyển sang 'bool', chỉ cần chuyển sang' bool'. –

+0

Nó là một biểu thức khẳng định, có giá trị là loại bool trong debug xây dựng và void trong bản phát hành, tôi giả định. Bạn có thể chứng minh mức độ hạn chế của việc sử dụng không? –

1

Nó sẽ chỉ đảm bảo rằng phần expr của macro được chuyển thành một bool.

+0

Nó sẽ là anyway. – GManNickG

+0

@GMan, thường có, nhưng có lẽ không. Có thể không có chuyển đổi tiềm ẩn thành 'bool' nhưng có một sự phủ định quá tải. –

+0

@Steven: Người viết một lớp như vậy là một thằng ngốc. Xin lỗi, tôi không căn cứ vào thực hành của tôi về những gì ai đó câm có thể viết. – GManNickG

1

Đây là thành ngữ đôi khi được sử dụng trong C++ để chuyển đổi thành kiểu boolean.

0

Trong ví dụ bạn đã cho chúng tôi thấy, !! hoàn toàn vô dụng. Tuy nhiên, nói chung, giá trị này được sử dụng là tương đương thô C99 trước khi đúc thành _Bool, nghĩa là 0 vẫn là 0 và bất kỳ giá trị nào khác sẽ trở thành 1.

+1

'!!' không hoàn toàn vô ích. '(expr) || uasserted (...) 'có thể không hoạt động như mong đợi trong C++ nếu' || 'là toán tử quá tải. Đây là lý do tại sao (expr) phải được đúc một cách rõ ràng để boolean đầu tiên. –

+0

Cảm ơn bạn đã nhắc tôi lý do tại sao tôi ghét ngôn ngữ với quá tải toán tử (hoặc ít nhất là các toán tử cần định nghĩa cố định về các toán tử khác có thể bị quá tải). –

+1

@Maxim: Lý do khủng khiếp. Quan sát: '!!' có thể không hoạt động như mong đợi trong C++ nếu '!' Là toán tử quá tải. Lập luận của bạn là tự đánh bại: có, một người nào đó có thể mang tính đạo đức với các toán tử, bạn không thể bỏ qua một cách thuận tiện họ có thể làm tương tự với vị trí của bạn. Nó vô dụng đối với bất kỳ chương trình chính thống nào, ai quan tâm đến những người không chính thống viết? Dựa vào các tập quán của bạn * mã * tốt, vì vậy bạn sẽ có các phương pháp lập trình * tốt *. – GManNickG

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