在我正在研究的一些代码中,我遇到了对真相和虚假的奇怪重新定义。我之前已经看过这样的事情,以便更加严格/确定地进行检查,但是这一点在我的脑海中有点奇怪,我想知道是否有人可以告诉我这些定义的原因是什么,请参阅下面我的评论旁边:
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE) // why not just define it as "true" or "1"?
此代码库中还有许多其他奇怪的东西。就像所有标准类型的重新定义一样:
#define myUInt32 unsigned integer // why not just use uint32_t from stdint?
所有这些小小的“怪癖”让我觉得我错过了一些明显的东西,但我真的看不出这一点:(
注意:严格来说这是c ++代码,但它可以从'c'项目移植。
答案 0 :(得分:34)
意图似乎是可移植性。
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
#define TRUE (!FALSE) // why not just define it as "true" or "1"?
它们在支持它的语言中有布尔类型(C ++),同时为不支持它的那些提供了有用的数值(C - 甚至是C99和C11,显然,尽管它们获取了显式的布尔数据类型)。 p>
尽可能使用布尔值有助于功能超载。
#define myUInt32 unsigned integer // why not just use uint32_t from stdint?
如果stdint
可用,那很好。你可以把这些事情视为理所当然,但这是一个广阔的世界!此代码识别出这一点。
免责声明:就个人而言,我会坚持标准并简单地声明1990年以后发布的编译器是先决条件。但我们不知道该项目的基本要求是什么。
TRWTF是有问题的代码的作者并未在评论中解释这一点。
答案 1 :(得分:11)
#define FALSE (1 != 1) // why not just define it as "false" or "0"?
我认为这是因为表达式(1!=1)
的类型取决于语言对布尔值的支持 - 如果它是C ++,则类型为bool
,否则它是int
。
另一方面,0
始终为int
,在两种语言中都有false
,但在C中无法识别。{/ p>
答案 2 :(得分:7)
严格来说这是c ++代码,但它可以从'c'项目移植。
这是关于如前所述的可移植性,但它实际上远远超出了。它是语言定义的巧妙利用,以符合语言。
这些看起来很荒谬的宏并不像第一眼看上去那么荒谬,但它们实际上是巧妙的,因为它们保证了TRUE
和FALSE
具有正确值的C和C ++(和true
和false
的类型)(即使编译器是没有这些关键字的C编译器,所以你不能轻易地编写像#define TRUE true
这样的东西)。
在C ++代码中,这样的构造将毫无用处,因为该语言将true
和false
定义为关键字。
但是,为了使C和C ++在相同的代码库中无缝地互操作,您需要“适用于两者的东西”(除非您想使用不同的代码样式)。
这些宏的定义方式是C ++标准的证明,它明确含糊true
和false
实际具有的值。 C ++标准规定:
bool类型的值为true或false [...]
零值,空指针值或空成员指针值转换为false;任何其他值都转换为true [...]
bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1。
请注意它是如何表示存在两个特定值以及它们的名称是什么,以及它们转换为哪些相应的整数值,但并未说明这些值是什么。您可能倾向于认为值显然是0
和1
(并且您可能已经猜到了 ),但事实并非如此。故意没有定义实际值。
这类似于如何定义指针(特别是nullpointer)。请记住,整数文字零转换为空指针,空指针转换为false
,比较相等...等等...等等
关于哪些转换为什么和什么都没有说很多,但它不说任何地方空指针必须具有零的二进制表示(事实上,存在一些奇特的架构,其中事实并非如此!)。
答案 3 :(得分:6)
其中许多都有历史原因,例如从C迁移的旧代码,非标准C ++编译器的代码,交叉编译器代码(可移植性),支持向后兼容性,遵循代码样式,坏习惯。
有些编译器对<cstdint>
等整数类型没有uint32_t
,或者没有<cstdbool>
。一个优秀的程序员必须定义所有内容并大量使用预处理器,以便在不同的编译器上很好地定义他的程序。
今天,我们可以使用<cstdint>
,true/false
,<cstdbool>
,......每个人都很高兴!
答案 4 :(得分:5)
这个定义的好处是避免从TRUE或FALSE到整数的隐式转换。这有助于确保编译器无法选择错误的函数重载。
答案 5 :(得分:4)
C没有本机布尔类型,所以你不能严格使用“false”或“true”而不在其他地方定义它们 - 那么你将如何定义呢?
相同的参数适用于myUInt32 - C最初没有uint32_t和stdint中的其他类型,因此这提供了一种确保获得正确大小整数的方法。如果移植到不同的体系结构,只需要将myUInt32的定义更改为32位宽的无符号整数 - 无论是长整数还是短整数。
答案 6 :(得分:1)
有一个很好的解释说明了false和FALSE之间的区别。虽然大多数答案已经解释过,但我认为它可能有助于进一步理解。 here