您阅读的代码非常糟糕,有几个原因。
首先,用户代码不应该定义ULONG_MAX
. 这是一个保留标识符,必须由编译器实现提供。
该定义不适合在预处理器中使用#if
。基本整数类型的_MAX
宏必须在那里可用。
(unsigned long)0
只是废话。每个人都应该使用0UL
,除非您知道您的编译器在这方面不符合所有最新的 C 标准。(我不知道。)
Even~0UL
不应该用于该值,因为unsigned long
可能(理论上)有填充位。-1UL
更合适,因为它不处理值的位模式。它使用无符号整数类型的保证算术属性。-1
将始终是无符号类型的最大值。所以~
只能在您绝对确定unsigned long
没有填充位的情况下使用。但是这样使用它是没有意义的。-1
服务更好。
正如您所观察到的,“重铸”已知的表达式unsigned long
只是多余的。我无法想象有任何编译器会对此产生错误。
当它们在预处理器中使用时,表达式的重铸可能是有意义的,但仅在非常有限的情况下,并且在那里它们的解释不同。
#if ((uintmax_t)-1UL) == SOMETHING
..
#endif
这里左边的值在UINTMAX_MAX
预处理器和后面的编译器阶段中赋值。所以
#define UINTMAX_MAX ((uintmax_t)-1UL)
将是编译器实现的适当定义。
要查看预处理器的值,请观察(uintmax_t)
内部没有强制转换而是未知标识符标记,()
并且它的计算结果为0
。减号然后被解释为二进制减号,所以我们有0-1UL
它是无符号的,因此是类型的最大值。但是这个技巧只有在强制转换包含单个标识符标记时才有效,而不是在你的示例中它有三个,并且如果整数常量有一个-
或+
符号。