2013-08-29 56 views
8

Tiêu đề <windows.h> có loại BOOL riêng. Nhìn kỹ vào việc triển khai, có vẻ như FALSE chỉ là một macro cho 0TRUE chỉ là một macro cho 1, nhưng tôi không chắc chắn điều này được chỉ định.Làm cách nào để chuyển đổi một BOOL thành một bool?

Cách thành ngữ để chuyển đổi BOOL thành bool là gì? Tôi có thể tưởng tượng rất nhiều cách có thể:

bool a = static_cast<bool>(x); 

bool b = x ? true : false; 

bool c = (x == TRUE); 

bool d = (x != FALSE); 

bool e = !!x; 

// ... 
+0

ý bạn là gì bởi "thành ngữ"? –

+0

'bool c = (x == FALSE)'? :) – Inspired

+0

Điều này có lẽ không phù hợp cho SO bởi vì nó sôi xuống sở thích cá nhân, tôi tin. – lpapp

Trả lời

6

Không cần cho bất kỳ chuyển đổi rõ ràng:

BOOL x = some_value; 
bool b = x; 

Việc chuyển đổi tiềm ẩn của một số loại để bool mang false ứng với giá trị 0, và true cho bất kỳ giá trị khác không.

Ngẫu nhiên, bạn đã cho chúng tôi biết cách <windows.h> xác định FALSETRUE. Làm thế nào để nó xác định BOOL? (Từ nhận xét của bạn, đó là typedef int BOOL;)

Nhưng một số trình biên dịch có thể cảnh báo về chuyển đổi tiềm ẩn này, mặc dù đó là mã hoàn toàn hợp lệ. Trình biên dịch được tự do cảnh báo về bất cứ điều gì họ thích, bao gồm cả phông chữ xấu xí mà bạn đã sử dụng để viết mã của mình. g ++, ví dụ, không phàn nàn về việc chuyển đổi, ngay cả với:

g++ -std=c++11 -pedantic -Wall -Wextra ... 

Nhưng theo this online Visual C++ compiler, VC++ không tạo ra một cảnh báo:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) 

Ngay cả với một static_cast, nó vẫn tạo ra cảnh báo.

Bạn có thể tránh cảnh báo bằng cách sử dụng !!x hoặc x ? true : false. Nhưng tôi không chắc liệu cách chữa trị có tốt hơn bệnh hay không.

Cách đơn giản và chính xác để thực hiện việc này đơn giản là chỉ định giá trị và dựa vào chuyển đổi tiềm ẩn để làm điều đúng (nó sẽ).

Nếu bạn có yêu cầu bổ sung để tránh cảnh báo trình biên dịch, thì điều này sẽ trở thành một câu hỏi về Visual C++ chứ không phải ngôn ngữ C++. Cũng có thể có một số cách để ngăn chặn các cảnh báo nhất định mà không thay đổi nguồn - mặc dù rủi ro mất đi những cảnh báo tương tự khi chúng thực sự có ý nghĩa. Trong một bình luận, Dieter Lücking đề xuất:

#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning) 

nhưng có vẻ như nó vẫn yêu cầu sửa đổi nguồn. Có lẽ có cái gì đó tương đương mà không.

Một điều nữa: kể từ BOOL thực sự gõ int, giải pháp đề xuất này:

bool c = (x == TRUE); 

không tương đương với những người khác. Bất kỳ số không khác int được coi là đúng, nhưng chỉ có giá trị 1bằng đến TRUE.Ví dụ trên sẽ đặt c thành false nếu x == 2 - trong khi if (x) vẫn coi đó là điều kiện thực. Không bao giờ so sánh các giá trị boolean cho sự bình đẳng với true hoặc TRUE. (So ​​sánh chúng với false hoặc FALSE là an toàn hơn, nhưng vẫn không cần thiết;. Đó là những gì các nhà điều hành ! là cho)

này tất cả các giả định rằng nếu bạn có một giá trị kiểu BOOL, bạn chỉ quan tâm cho dù đó là falsish hoặc truthy (zero hoặc khác không). Thật không may, điều này có thể không phải lúc nào cũng đúng. Khi Ben Voight's answer chỉ ra, API của Microsoft có ít nhất một hàm, GetMessage, trả về kết quả là BOOLkhông phải là giá trị Boolean đơn giản. Trong trường hợp khủng khiếp như vậy, việc chuyển đổi từ BOOL sang bool không thích hợp nếu bạn cần phân biệt giữa nhiều giá trị khác 0.

Cuối cùng, tôi đổ lỗi cho Microsoft để xác định loại BOOL cho một ngôn ngữ đã có loại được xây dựng hoàn toàn tốt trong loại bool. Thực ra điều đó không công bằng lắm; nó được sử dụng trong các API cần phải truy cập được từ cả C và C++. Định nghĩa của Microsoft về BOOL có thể quay lại triển khai C của họ, nơi nó có ý nghĩa - ít nhất là trước C99, mà Microsoft vẫn không hỗ trợ. (Tôi không biết liệu của Microsoft trình biên dịch C hỗ trợ _Bool Thậm chí nếu có, _Bool có một số khác biệt về ngữ nghĩa từ int, và thay đổi định nghĩa của BOOL có thể phá vỡ một số mã -.. Đặc biệt là mã có sử dụng GetMessage)

+2

Điều này mang lại cho tôi một cảnh báo trình biên dịch.Nếu không tôi sẽ không hỏi :) – fredoverflow

+0

'typedef int BOOL; ' – fredoverflow

+1

@FredOverflow: Cảnh báo là gì? (Và tại sao bạn không đề cập đến điều đó, và trích dẫn cảnh báo, trong câu hỏi ban đầu của bạn?) Trình biên dịch có thể cảnh báo về bất cứ điều gì họ thích; gcc, ví dụ, * không * cảnh báo về một chuyển đổi ngầm từ 'int' thành 'bool'. Và vui lòng cập nhật câu hỏi của bạn để hiển thị typedef đó. –

0

Đó là khó có thể nói như thế nào các lập trình viên win32 sẽ làm điều đó, nhưng IMHO nó nên được thực hiện bởi:

bool c = (X == TRUE); 

hoặc

bool d = (x != FALSE); 

tôi nghĩ rằng đó là một p xấu ractice để chuyển tiếp trên macro (hoặc bất kỳ công cụ được xác định trước nào khác)
sự kiên trì.

Một ngày TRUE có thể trở thành 0 và FALSE 1;)

+1

Ngày hôm đó, sắp xếp: ['VARIANT_BOOL'] (http://msdn.microsoft.com/en-us/library/cc237864.aspx) có thể được gán' VARIANT_FALSE' và 'VARIANT_TRUE' với giá trị thứ hai được xác định như '(viết tắt) -1', nói cách khác là 0xFFFF. Trên Windows, tôi khuyên bạn nên luôn sử dụng 'bool d = (x! = FALSE);'. Bạn không thể mong đợi mọi người trong nhóm của bạn biết cách chuyển đổi từ 'VARIANT_BOOL' thành' BOOL' đúng cách. – IInspectable

0

Không có cách nào an toàn để làm điều đó, bởi vì Win32 BOOLmore than two values.

+0

Giả sử bạn cần giữ lại các giá trị đó. Nếu nó được sử dụng một cách an toàn, bạn chỉ nên quan tâm xem đó là sự thật hay giả tạo. –

+0

@Keith: Điều đó đúng đối với nhiều API, nhưng cái tôi liên kết để trả về giá trị từ ba lớp tương đương. –

+0

Đó là một API ngu ngốc, ngu ngốc, ngu ngốc. (Thay đổi kiểu trả về từ 'BOOL' thành' int' sẽ giải quyết vấn đề đó và không tạo sự khác biệt cho API.) –

1

tôi sử dụng một macro:

#define _bool(b) (!!(b)) 

IMO, làm cho mã của tôi dễ đọc hơn.

CHỈNH SỬA: người nhận xét đã thách thức việc tôi sử dụng dấu gạch dưới trong tên macro. Để giải quyết vấn đề này, đây là phiên bản mới vẫn còn chung chung và vẫn sử dụng cùng tên _bool, nhưng tuân thủ theo this.

namespace MyBool 
{ 
    template<typename T> inline bool _bool(const T b) 
    { 
     return !!b; 
    } 
} 

using namespace MyBool; 
+0

Tên bắt đầu bằng dấu gạch dưới trong không gian tên chung được đặt trước (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier) . – IInspectable

+0

Không phải là vấn đề đối với tôi. Macro này chỉ được sử dụng bởi mã của riêng tôi và được mở rộng bởi bộ xử lý trước, do đó trình biên dịch và không gian tên không biết gì về nó. Dù sao, người ta có thể sử dụng '__bool'. – avo

+0

Tên có chứa dấu gạch dưới kép được đặt trước ** ở mọi nơi **. Điều này không có gì để làm với ** mã ** của bạn. Các quy tắc có để ngăn chặn xung đột tên với việc thực hiện C++. Bạn chắc chắn không muốn tiêu đề thư viện chuẩn bao gồm bảo vệ xung đột với mã bằng cách sử dụng nó. Một thay thế an toàn sẽ là: 'bool bool_ (const BOOL b) {return !! b;}' – IInspectable

0

Đây là một câu hỏi về ý kiến, nhưng tôi nghĩ rằng có những đối số khách quan được thực hiện cho các tùy chọn khác nhau.

Sự lựa chọn tốt nhất là:

bool d = (x != FALSE); 

Điều này làm cho mục đích rất rõ ràng đối với người đọc, không dựa vào chuyển đổi tiềm ẩn, và làm cho nó rõ ràng rằng có nhiều đang diễn ra hơn một nhiệm vụ đơn giản.

Sự lựa chọn tốt nhất thứ hai là:

bool b = x ? true : false; 

Tuy nhiên, để người đọc bình thường, có thể có vẻ như một sự lặp thừa.

Tôi cố gắng tránh chuyển đổi ngầm định trong các bài tập vì việc chuyển đổi sai là một nguồn lỗi đáng ngạc nhiên. Ngay cả khi tôi biết chuyển đổi tiềm ẩn sẽ làm điều đúng, tôi có xu hướng làm điều đó một cách rõ ràng, điều này có thể hữu ích cho người nào đó đọc mã trong tương lai. Rõ ràng cũng cho phép bạn duy trì cảnh báo chuyển đổi được bật để bạn nắm bắt các chuyển đổi tiềm ẩn khác mà bạn không biết mình đã sử dụng (ab).

Các lựa chọn thay thế đều có những hạn chế nghiêm trọng hơn.

bool a = static_cast<bool>(x); 

Điều này giống như đóng cọc hình vuông vào lỗ tròn. Đó là thanh lịch hơn để viết một biểu thức tự nhiên trả về đúng loại.

bool c = (x == TRUE); 

Nó thường là một ý tưởng tồi để so sánh với TRUE, vì giá trị khác không khác sẽ chuyển đổi sang sai, đó là gần như chắc chắn một lỗi.

bool e = !!x; 

Quá thông minh so với các lựa chọn thay thế thể hiện chính xác ý bạn. (Tôi phạm tội đã làm điều này trong quá khứ.)

bool f = x; 

Cảnh báo hiệu suất MSVC++ phát ra trên chuyển đổi hoàn toàn có vẻ hợp lý. Trình biên dịch phải tạo thêm mã để chuyển đổi một int thành bool. Việc giao nhiệm vụ cho phép ít manh mối về công việc phụ này. Nếu nó trong một vòng lặp chặt chẽ, bạn có thể quan tâm. (Cấp, cảnh báo hoạt động vào tùy chọn static_cast dường như nghiêm trọng, nhưng chúng tôi đã phán quyết rằng hiện như ít thanh lịch.)

Các db biểu hiện rõ mục đích và làm cho nó rõ ràng rằng có nhiều xảy ra ở đây hơn một nhiệm vụ trực tiếp.

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