项目里,有个之前兄弟留下的库。硬生生将BOOL定义为bool,极为不和谐。今天半夜忽然回想起bool 跨模块返回值会出问题,遂查了查资料。看到有位小兄弟在stackoverflow上的提问。
http://stackoverflow.com/questions/830067/when-should-bool-and-bool-be-used-in-c
底下就有老兄做了解答
Matthew Wilson discusses BOOL
, bool
, and similar in section 13.4.2 of Imperfect C++. Mixing the two can be problematic, since they generally have different sizes (and so pointers and references aren't interchangeable), and since bool
isn't guaranteed to have any particular size. Trying to use typedefs or conditional compilating to smooth over the differences between BOOL
and bool
or trying to allow for a single Boolean type to work in both C and C++ is even worse:
#if defined(__cplusplus) || \
defined(bool) /* for C compilation with C99 bool (macro) */
typedef bool bool_t;
#else
typedef BOOL bool_t;
#endif /* __cplusplus */
This approach means that a function's return type can differ depending on which language calls it; Wilson explains that he's seen more than one bug in his own code and others' that results from this. He concludes:
The solution to this imperfection is, as it so often is, abstinence. I never usebool
for anything that can possibly be accessed across multiple link units—dynamic/static libraries, supplied object files—which basically means not in functions or classes that appear outside of header files. The practical answer, such as it is, is to use a pseudo-Boolean type, which is the size ofint
.
In short, he would agree with your approach.
================================================================================
If you wish to use a function written in C++ (for example embedded in DLL library) in managed program (for example in C#), you have to use BOOL. If you return bool, the result will always be true - this is known bug for a long time and apparently not yet resolved (VS 2010, .NET Framework 4).
=======================================================================================
还挖出来两篇老文章
BOOL vs. VARIANT_BOOL vs. BOOLEAN vs. bool
Still more ways of saying the same thing. Why so many?
Because each was invented by different people at different times to solve different problems.
BOOL
is the oldest one. Its definition is simply
typedef int BOOL;
The C programming language uses "int" as its boolean type, and Windows 1.0 was written back when C was the cool language for systems programming.
Next came BOOLEAN
.
typedef BYTE BOOLEAN;
This type was introduced by the OS/2 NT team when they decided to write a new operating system from scratch. It lingers in Win32 in the places where the original NT design peeks through, like the security subsystem and interacting with drivers.
Off to the side came VARIANT_BOOL
.
typedef short VARIANT_BOOL; #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0)
This was developed by the Visual Basic folks. Basic uses -1
to represent "true" and 0
to represent "false", and VARIANT_BOOL
was designed to preserve this behavior.
Common bug: When manipulating VARIANT
s of type VT_BOOL
, and you want to set a boolean value to "true", you must use VARIANT_TRUE
. Many people mistakenly use TRUE
or true
, which are not the same thing as VARIANT_TRUE
. You can cause problem with scripting languages if you get them confused. (For symmetry, you should also use VARIANT_FALSE
instead of FALSE
or false
. All three have the same numerical value, however. Consequently, a mistake when manipulating "false" values is not fatal.)
Newest on the scene is bool
, which is a C++ data type that has the value true
or false
. You won't see this used much (if at all) in Win32 because Win32 tries to remain C-compatible.
(Note that C-compatible isn't the same as C-friendly. Although you can do COM from C, it isn't fun.)
===============================================================================
What's the difference between int and INT, long and LONG, etc?
When you go through Windows header files, you'll see types with names INT
,LONG
, CHAR
, and so on. What's the difference between these types and the uncapitalized ones?
Well, there isn't one any more.
What follows is an educated guess as to the story behind these types.
The application binary interface for an operating system needs to be unambiguous. Everybody has to agree on how parameters are passed, which registers are preserved, that sort of thing. A compiler need only enforce the calling convention rules at the boundary between the application and the operating system. When a program calls another function provided by that same program, it can use whatever calling convention it likes. (Not a true statement but the details aren't important here.) Therefore, a calling convention attribute on the declarations of each operating system function is sufficient to get everybody to agree on the interface.
However, another thing that everybody needs to agree on is the sizes of the types being passed to those functions or used in structures that cross the application/operating system boundary. The C language makes only very loose guarantees as to the sizes of each of the types, so language types like int
andlong
would be ambiguous. One compiler might decide that a long
is a 32-bit integer, and another might decide that it's a 64-bit integer. To make sure that everybody was on the same page, the Windows header files defined "platform types" like INT
and LONG
with prescribed semantics that everybody could agree on. Each compiler vendor could tweak the Windows header file to ensure that the type definition for these platform types resulted in the value that Windows expected. One compiler might use typedef long LONG
another might usetypedef __int32 LONG
.
Okay, but this doesn't explain VOID
. Maybe VOID
was added for the benefit of compilers which didn't yet support the then-new ANSI C standard type void
? Those older compilers could typedef int VOID;
and functions that were declared as "returning VOID
" would be treated as if they returned an integer that was always ignored. Or maybe it was just added to complete the set, who knows.
In the intervening years, most if not all compilers which target Windows have aligned their native types with Windows' platform types. An int
is always a 32-bit signed integer, as is a long
. As a result, the distinction between language types and platform types is now pretty much academic, and the two can be used interchangeably. New Windows functions tend to be introduced with language types, leaving platform types behind only for compatibility.